Zum Inhalt

pipeline/tests/webui/test_system_routes.py

# SPDX-License-Identifier: AGPL-3.0-or-later

from __future__ import annotations

from pathlib import Path

import pytest
from fastapi import FastAPI
from starlette.testclient import TestClient

from autosplat.doctor import CheckResult
from autosplat.webui.routes import system as system_route


def test_system_page_lists_external_tools(app: FastAPI) -> None:
    with TestClient(app) as client:
        r = client.get("/system")
    assert r.status_code == 200
    body = r.text
    for tool in ("ffmpeg", "colmap", "brush"):
        assert tool in body


def test_system_page_reports_a_missing_bundled_viewer(app: FastAPI, tmp_path: Path) -> None:
    """The defect this page exists for: a missing viewer used to be invisible."""
    app.state.cfg.viewer.supersplat_dist_path = tmp_path / "nope"
    with TestClient(app) as client:
        r = client.get("/system")
    assert r.status_code == 200
    assert "supersplat" in r.text.lower()
    assert "missing" in r.text.lower()


def test_system_page_names_the_role_of_each_viewer(app: FastAPI) -> None:
    with TestClient(app) as client:
        body = client.get("/system").text
    # The charter, rendered: three viewers, three jobs.
    assert "clean up" in body.lower()
    assert "share" in body.lower()
    assert "walk" in body.lower()


def test_nav_links_to_system(app: FastAPI) -> None:
    """Trailing slash matches `/system`'s canonical `APIRouter(prefix="/system")`
    + `"/"` route — same shape as `/captures/` and `/jobs/` in this nav, which
    both already carry it. Linking the bare path costs an extra 307 per click."""
    with TestClient(app) as client:
        body = client.get("/").text
    assert 'href="/system/"' in body


def test_setup_button_hidden_when_no_tool_is_missing(
    app: FastAPI, monkeypatch: pytest.MonkeyPatch
) -> None:
    """A repair button on a healthy system is noise — it must only appear
    when `missing_required_tools`'s underlying checks actually report one."""
    monkeypatch.setattr(
        system_route,
        "run_doctor",
        lambda cfg: [CheckResult(name="colmap", ok=True, detail="1.2.3")],
    )
    with TestClient(app) as client:
        body = client.get("/system/").text
    assert "Run setup" not in body
    assert 'action="/system/setup"' not in body


def test_setup_button_shown_when_a_required_tool_is_missing(
    app: FastAPI, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setattr(
        system_route,
        "run_doctor",
        lambda cfg: [CheckResult(name="colmap", ok=False, detail="not in PATH")],
    )
    with TestClient(app) as client:
        body = client.get("/system/").text
    assert "Run setup" in body
    assert 'action="/system/setup"' in body
    # The user must not be surprised by a Terminal window appearing.
    assert "Terminal" in body
    assert "password" in body.lower()


def test_setup_post_triggers_run_first_run_setup_once_with_bundled_script(
    app: FastAPI, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
    """The POST must never itself shell out to osascript — only the injected
    stand-in is allowed to see the call. If this test opened a real Terminal
    window, it would be wrong."""
    script = tmp_path / "install_deps.sh"
    calls: list[Path] = []
    monkeypatch.setattr(system_route.desktop, "_bundled_install_script", lambda: script)
    monkeypatch.setattr(
        system_route.desktop, "run_first_run_setup", lambda s: calls.append(s)
    )

    with TestClient(app) as client:
        r = client.post("/system/setup")

    assert r.status_code == 200  # redirect to /system/ followed
    assert calls == [script]
    assert "Terminal" in r.text


def test_setup_post_surfaces_missing_install_script(
    app: FastAPI, monkeypatch: pytest.MonkeyPatch
) -> None:
    """A missing resource is displayed, never silently hidden — even when the
    resource is the install script itself."""
    monkeypatch.setattr(system_route.desktop, "_bundled_install_script", lambda: None)
    triggered = False

    def _fail_if_called(*args: object, **kwargs: object) -> None:
        nonlocal triggered
        triggered = True

    monkeypatch.setattr(system_route.desktop, "run_first_run_setup", _fail_if_called)

    with TestClient(app) as client:
        r = client.post("/system/setup")

    assert r.status_code == 200
    assert triggered is False
    assert "install_deps.sh" in r.text
    assert "did not start" in r.text.lower() or "could not find" in r.text.lower()