viggle-mine-workflow / tests /test_workflow_http.py
ZIP Space Deployer
Deploy ZIP — 2026-10-14 15:17 UTC
18bfeb9
Raw History Blame Contribute Delete
7.92 kB
"""Actual FastAPI/Gradio routes; CPU media only, no simulated inference."""
import copy
import json
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
import workflow_artifacts as a
from cpu_preview import cpu_core
from workflow_ui import create_workflow
from workflow_nodes import Nodes
from workflow_media import output_file
def test_gpu_registration_does_not_duplicate_canvas_load_events_or_app_routes():
# Construction probe only: never substitutes GPU inference in production.
base, base_app = create_workflow(cpu_core())
core = cpu_core()
def registration_probe(value: str):
return value
core.render_all_segments = registration_probe
registered, app = create_workflow(core, register_gpu=True)
def load_count(demo):
return sum(any(event == "load" for _, event in dep["targets"])
for dep in demo.get_config_file()["dependencies"])
try:
assert load_count(registered) == load_count(base)
assert len(registered.fns) == len(base.fns) + 1
# Launch will add these exactly once; custom routes are already present.
assert not any(getattr(r, "path", None) == "/config" for r in app.routes)
app = type(app).create_app(registered, app=app)
assert sum(m.cls.__name__ == "BrotliMiddleware" for m in app.user_middleware) == 1
assert sum(m.cls.__name__ == "CustomCORSMiddleware" for m in app.user_middleware) == 1
with TestClient(app) as client:
config = client.get("/config").json()
ids = {c["id"] for c in config["components"]}
assert ids <= set(app.get_blocks().blocks)
canvas = next(c for c in config["components"] if c["type"] == "workflowcanvas")
result = client.post("/gradio_api/component_server", json={
"component_id": canvas["id"], "fn_name": "get_workflow_key",
"data": {}, "session_hash": "startup-regression"})
assert result.status_code == 200
finally:
registered.close()
base.close()
@pytest.fixture(scope="module")
def client():
demo, app = create_workflow(cpu_core())
app = type(app).create_app(demo, app=app)
# Production launch adds this path. TestClient does not call launch().
demo.allowed_paths = [str(a.PUBLIC)]
with TestClient(app) as c:
yield c
demo.close()
def test_native_config_routes_and_canvas_default(client):
response = client.get("/", follow_redirects=False)
assert response.status_code == 307 and "ui=canvas" in response.headers["location"]
assert a.ID.fullmatch(client.cookies["vm_workspace"])
config = client.get("/config").json()
assert config["version"] == "6.30.0"
assert any(c["type"] == "workflowcanvas" for c in config["components"])
# Bound-function endpoints are intentionally undocumented; /info lists
# public generated-pipeline endpoints, while config contains both.
assert client.get("/gradio_api/info").status_code == 200
names = {d["api_name"] for d in config["dependencies"]}
for name in Nodes(cpu_core()).bindings():
assert "predict_fn_" + name.replace(" ", "_") in names
def test_canvas_redirect_keeps_browser_https_behind_hf_proxy(client):
# Reproduce HF's proxy boundary: Python receives HTTP but the embedding
# browser is on HTTPS. Never derive the redirect scheme from this scope.
from urllib.parse import urljoin, parse_qs, urlsplit
response = client.get("http://fffiloni-viggle-mine-workflow.hf.space/?__theme=light",
follow_redirects=False)
assert response.status_code == 307
location = response.headers["location"]
assert location.startswith("/?") and not location.startswith("//")
browser_target = urljoin("https://fffiloni-viggle-mine-workflow.hf.space/", location)
assert urlsplit(browser_target).scheme == "https"
assert parse_qs(urlsplit(browser_target).query) == {"__theme":["light"],"ui":["canvas"]}
assert response.headers["cache-control"] == "no-store"
# HTML rendering requires launch()'s theme setup; the real-server smoke
# follows this redirect and checks the resulting page separately.
def test_source_picker_bridge_and_legacy_retention(client, prepared, point_payload):
ident = prepared["id"]
page = client.get("/picker/", params={"session": ident})
assert page.status_code == 200 and "Save points &amp; continue" not in page.text
assert "Save points & continue" in page.text
model = client.get(f"/picker/api/session/{ident}").json()
assert model["coordinate_space"] == "normalized_source"
assert len(model["anchors"]) == 3
assert client.get(model["anchors"][0]["url"]).headers["content-type"] == "image/png"
saved = client.post(f"/picker/api/session/{ident}/points", json=point_payload)
assert saved.status_code == 200 and saved.json()["saved"]
assert a.points(prepared)["anchors"] == saved.json()["anchors"]
# No queue/SSE is involved in saving or reloading the picker.
again = client.get(f"/picker/api/session/{ident}").json()
assert again["anchors"][0]["points"] == point_payload["anchors"][0]["points"]
assert client.get("/picker/").status_code == 200
fallback = client.get("/picker/legacy/", params={"session":ident})
assert fallback.status_code == 200 and "Save points to Workflow" in fallback.text
assert prepared["manifest_path"] in fallback.text and ident in fallback.text
legacy = client.get("/picker/api/manifest", params={"path": prepared["manifest_path"]})
assert legacy.status_code == 200
assert client.get(legacy.json()["anchors"][0]["url"]).status_code == 200
wrong = copy.deepcopy(point_payload); wrong["coordinate_space"] = "stabilized"
assert client.post(f"/picker/api/session/{ident}/points", json=wrong).status_code == 400
assert client.post(f"/picker/api/session/{ident}/points", json=point_payload,
headers={"origin":"https://another.example"}).status_code == 403
assert client.get(f"/artifact/{ident}").json()["kind"] == "prepared"
def test_recovery_browser_extracts_exact_stabilized_input_frame(client, camera, prepared):
# A manifest fixture stands in for a completed generation. Only the frame
# extraction below is real; no assertion here implies GPU generation.
passed = a.create("pass_a", {"camera_id":camera["id"], "preparation_id":prepared["id"],
"stabilized_generated":camera["stable_video"], "final_video":prepared["meta"]["normalized"]},
files=[camera["stable_video"]], parents=[camera["id"]])
ident = passed["id"]
data = client.get(f"/recovery/api/{ident}").json()
assert data["coordinate_space"] == "stabilized"
assert data["url"] == output_file(camera["stable_video"])["url"]
assert data["url"] != output_file(prepared["meta"]["normalized"])["url"]
assert client.get("/recovery/", params={"checkpoint":ident}).status_code == 200
response = client.post(f"/recovery/api/{ident}/select", json={"time":1.501})
assert response.status_code == 200
selected = response.json()
assert selected["time"] == 1.5 and selected["frame"] == 30
artifact = a.load(Nodes(cpu_core()).prepare_recovery(a.card(passed,"Saved A")), "recovery")
assert artifact["reacq_time"] == selected["time"] and artifact["pass_a_id"] == ident
from PIL import Image
import media
expected = a.PUBLIC / "recovery-exact-frame.png"
media.extract_frame(camera["stable_video"], expected, 30)
assert Image.open(expected).tobytes() == Image.open(artifact["candidate"]).tobytes()
assert client.post(f"/recovery/api/{ident}/select", json={"time":999}).status_code == 400
assert client.post(f"/recovery/api/{ident}/select", json={"time":data["start"]}).status_code == 400
assert client.post(f"/recovery/api/{ident}/select", json={"time":data["end"]}).status_code == 400