from datetime import datetime from pathlib import Path from uuid import uuid4 import base64 import pytest from tests.config_reader import load_config from playwright_tests.planning import build_plan from playwright_tests.setup_page import SetupPage def pytest_configure(config): run = datetime.now().strftime("%Y%m%d_%H%M%S") + "_" + uuid4().hex[:8] folder = Path(config.rootpath) / "reports" / "playwright" / run folder.mkdir(parents=True, exist_ok=True) config._setup_report_folder = folder config.option.htmlpath = str(folder / "report.html") config.option.self_contained_html = True config.option.output = str(folder / "artifacts") @pytest.fixture(scope="session") def browser_context_args(browser_context_args): return {**browser_context_args, "viewport": {"width": 1600, "height": 1000}} @pytest.fixture def setup_config(): return load_config() @pytest.fixture def setup_plan(request, setup_config): plan = build_plan(setup_config, request.config.getoption("--setup-flow"), request.config.getoption("--token-products")) resume_id = request.config.getoption("--resume-token-id") if resume_id and (request.config.getoption("--setup-flow") != "token" or len(plan["tokens"]) != 1): raise pytest.UsageError("--resume-token-id requires --setup-flow token and exactly one product.") plan["resume_token_id"] = resume_id return plan @pytest.fixture def setup_app(request, setup_plan, setup_config, page): # setup_plan validates all dates before login or any save operation. if not request.config.getoption("headed"): raise pytest.UsageError("Setup login requires manual CAPTCHA: run with --headed.") page.set_default_timeout(30_000) folder = request.config._setup_report_folder / request.node.name folder.mkdir(parents=True, exist_ok=True) app = SetupPage(page, folder) request.node._setup_app = app app.login(setup_config, request.config.getoption("--captcha-timeout") * 1000) return app @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() app = getattr(item, "_setup_app", None) if app and report.when in ("setup", "call"): if report.failed and not app.page.is_closed(): try: app.capture("failure_state") except Exception: pass # Keep the original failure if the browser has disconnected. if report.when == "call" or report.failed: from pytest_html import extras report.extras = list(getattr(report, "extras", [])) + [ extras.png(base64.b64encode(path.read_bytes()).decode("ascii"), name=name) for name, path in app.screenshots ]