import json from pathlib import Path from fastapi.testclient import TestClient from app.main import app WORKSPACE = Path(__file__).resolve().parent.parent.parent def _create_published_echo_workflow(client) -> str: definition = { "name": "echo-flow", "version": 1, "nodes": [ { "id": "step", "node_type": "echo", "inputs": {"file_uri": "input.video_uri"}, } ], "edges": [], "entry_inputs": {"video_uri": "file"}, "final_outputs": {"result": "step.file_uri"}, } manifest = json.loads( (WORKSPACE / "wov-node-echo" / "node.manifest.json").read_text(encoding="utf-8") ) assert client.post("/api/admin/nodes", json=manifest).status_code == 200 client.post( "/api/admin/workflows", json={ "id": "echo-app", "name": "Echo App", "description": "upload a file", "definition": definition, }, ) client.post("/api/admin/workflows/echo-app/publish") return "echo-app" def test_upload_run_progress_and_download() -> None: with TestClient(app) as client: workflow_id = _create_published_echo_workflow(client) apps = client.get("/api/apps") assert apps.status_code == 200 assert any(item["id"] == workflow_id for item in apps.json()) uploaded = client.post( f"/api/apps/{workflow_id}/runs", files={"file": ("sample.txt", b"hello from upload", "text/plain")}, ) assert uploaded.status_code == 200 run_id = uploaded.json()["id"] assert uploaded.json()["status"] == "QUEUED" run = client.get(f"/api/runs/{run_id}") assert run.status_code == 200 assert run.json()["input_uri"].endswith("sample.txt") assert run.json()["artifacts"] == [] scheduler = app.state.scheduler scheduler.execute_run(run_id) completed = client.get(f"/api/runs/{run_id}") assert completed.status_code == 200 assert completed.json()["status"] == "COMPLETED" artifact_names = [item["name"] for item in completed.json()["artifacts"]] assert "result" in artifact_names artifacts = client.get(f"/api/runs/{run_id}/artifacts") assert artifacts.status_code == 200 assert len(artifacts.json()) >= 1 downloaded = client.get(f"/api/runs/{run_id}/artifacts/result") assert downloaded.status_code == 200 assert b"hello from upload" in downloaded.content assert client.get(f"/api/runs/{run_id}/artifacts/missing").status_code == 404 assert client.get("/api/runs/missing").status_code == 404 assert client.get("/api/runs/missing/artifacts").status_code == 404 db = app.state.db db.create_artifact( { "run_id": run_id, "node_id": "step", "name": "missing-file", "uri": str(Path(__file__).resolve().parent / "not-exists.bin"), "mime_type": "text/plain", "size": 0, } ) assert client.get(f"/api/runs/{run_id}/artifacts/missing-file").status_code == 404 runs = client.get("/api/runs") assert runs.status_code == 200 assert any(item["id"] == run_id for item in runs.json()) def test_upload_rejects_unpublished_workflow() -> None: with TestClient(app) as client: client.post( "/api/admin/workflows", json={ "id": "draft", "name": "Draft", "definition": { "name": "Draft", "version": 1, "nodes": [], "edges": [], }, }, ) response = client.post( "/api/apps/draft/runs", files={"file": ("x.txt", b"x", "text/plain")}, ) assert response.status_code == 404 response = client.post( "/api/apps/missing/runs", files={"file": ("x.txt", b"x", "text/plain")}, ) assert response.status_code == 404 def test_upload_rejects_workflow_without_version() -> None: with TestClient(app) as client: db = app.state.db db.upsert_workflow( {"id": "empty", "name": "Empty", "published": 1, "latest_version": 0} ) response = client.post( "/api/apps/empty/runs", files={"file": ("x.txt", b"x", "text/plain")}, ) assert response.status_code == 422