Skip to content

Conftest

conftest

Root conftest — in-process Gradio server fixtures for xil-gui UI tests.

Complements the subprocess-based tests in tests/test_xil_gui_integration.py: these fixtures launch the dashboard in-process (fast, ephemeral port) for gradio_client API tests and optional Playwright UI smoke tests.

Requirements (beyond the [gui]/dev extras, which cover gradio and gradio_client)::

pip install pytest-playwright
playwright install chromium

All heavy imports happen inside fixtures, so collecting the suite never fails when gradio or playwright is absent — tests that request these fixtures are skipped instead.

Interaction note: the autouse fixture in tests/conftest.py deletes XIL_PROJECTROOT for every test. The server built here captures its workspace at build time, but xil_gui callbacks re-resolve get_workspace_root() per request — tests that exercise workspace-dependent callbacks should also request gui_env to pin the environment for the duration of the test.

workspace_dir

workspace_dir(tmp_path_factory)

Empty, isolated workspace directory the GUI session is bound to.

Source code in conftest.py
@pytest.fixture(scope="session")
def workspace_dir(tmp_path_factory):
    """Empty, isolated workspace directory the GUI session is bound to."""
    return tmp_path_factory.mktemp("gui-workspace")

gradio_server

gradio_server(workspace_dir)

Launch the xil-gui dashboard once, in-process, for the whole session.

Mirrors xil_gui.main(): builds via _build_app(), launches with prevent_thread_lock=True so pytest keeps control, then attaches the /xil/* FastAPI routes (only possible after launch, when demo.app is the serving FastAPI instance). Yields the base URL.

Source code in conftest.py
@pytest.fixture(scope="session")
def gradio_server(workspace_dir):
    """Launch the xil-gui dashboard once, in-process, for the whole session.

    Mirrors xil_gui.main(): builds via _build_app(), launches with
    prevent_thread_lock=True so pytest keeps control, then attaches the
    /xil/* FastAPI routes (only possible after launch, when demo.app is
    the serving FastAPI instance). Yields the base URL.
    """
    pytest.importorskip("gradio", reason="requires the [gui] extra")

    mp = pytest.MonkeyPatch()
    mp.setenv("XIL_PROJECTROOT", str(workspace_dir))

    from xil_pipeline.xil_gui import _build_app, _register_sfx_routes

    port = _free_port()
    demo = _build_app()
    demo.launch(
        server_name="127.0.0.1",
        server_port=port,
        prevent_thread_lock=True,
        allowed_paths=[str(workspace_dir)],
        show_error=True,
        quiet=True,
    )
    _register_sfx_routes(demo.app)
    yield f"http://127.0.0.1:{port}"
    demo.close()
    mp.undo()

gui_env

gui_env(workspace_dir, monkeypatch)

Pin XIL_PROJECTROOT to the GUI session workspace for one test.

Needed because tests/conftest.py clears the variable per test while xil_gui callbacks re-resolve the workspace on every request.

Source code in conftest.py
@pytest.fixture
def gui_env(workspace_dir, monkeypatch):
    """Pin XIL_PROJECTROOT to the GUI session workspace for one test.

    Needed because tests/conftest.py clears the variable per test while
    xil_gui callbacks re-resolve the workspace on every request.
    """
    monkeypatch.setenv("XIL_PROJECTROOT", str(workspace_dir))
    return workspace_dir

base_url

base_url(gradio_server)

pytest-playwright reads this fixture name for page.goto('/') support.

Source code in conftest.py
@pytest.fixture(scope="session")
def base_url(gradio_server):
    """pytest-playwright reads this fixture name for page.goto('/') support."""
    return gradio_server

app_page

app_page(page, gradio_server)

A Playwright page navigated to the dashboard, with Gradio hydrated.

Gradio is a Svelte SPA — 'load' fires before components mount, so wait for the dashboard's own "# xil-pipeline" heading (xil_gui.py renders it as the first Markdown block; generated Gradio class names are NOT stable across versions).

Source code in conftest.py
@pytest.fixture
def app_page(page, gradio_server):
    """A Playwright page navigated to the dashboard, with Gradio hydrated.

    Gradio is a Svelte SPA — 'load' fires before components mount, so wait
    for the dashboard's own "# xil-pipeline" heading (xil_gui.py renders it
    as the first Markdown block; generated Gradio class names are NOT
    stable across versions).
    """
    page.goto(gradio_server)
    page.get_by_role("heading", name="xil-pipeline").wait_for(timeout=15_000)
    return page

create_show_via_ui

create_show_via_ui(page)

Callable that drives the Setup tab's "Create show" flow to completion.

A fixture (not a plain importable function) because two conftest.py files exist in this repo (this one and tests/conftest.py) — "conftest" as a bare module name is ambiguous for direct imports, but pytest's own fixture resolution has no such ambiguity. Shared by test_webapp_smoke.py and test_gui_pipeline_lifecycle.py, both of which need a fresh show scaffolded through the real UI before exercising later stages.

Source code in conftest.py
@pytest.fixture
def create_show_via_ui(page):
    """Callable that drives the Setup tab's "Create show" flow to completion.

    A fixture (not a plain importable function) because two conftest.py
    files exist in this repo (this one and tests/conftest.py) — "conftest"
    as a bare module name is ambiguous for direct imports, but pytest's own
    fixture resolution has no such ambiguity. Shared by test_webapp_smoke.py
    and test_gui_pipeline_lifecycle.py, both of which need a fresh show
    scaffolded through the real UI before exercising later stages.
    """
    def _create(show_name: str) -> None:
        page.locator("#init-show-name textarea").fill(show_name)
        page.locator("#init-create-btn").click()
        page.wait_for_function(
            "document.querySelector('#init-log textarea').value.includes('[exit')",
            timeout=30_000,
        )
        log = page.locator("#init-log textarea").input_value()
        assert "[exit 0]" in log, f"show creation failed:\n{log}"

    return _create

api_client

api_client(gradio_server)

gradio_client for API-level regression tests (fast path).

Use this for pipeline-logic assertions; save Playwright for UI smoke tests.

Source code in conftest.py
@pytest.fixture(scope="session")
def api_client(gradio_server):
    """gradio_client for API-level regression tests (fast path).

    Use this for pipeline-logic assertions; save Playwright for UI smoke
    tests.
    """
    from gradio_client import Client

    return Client(gradio_server)