124 lines
4.8 KiB
Python
124 lines
4.8 KiB
Python
"""Step 4 tests: Langflow import pipeline (Langflow faked, LFX real)."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from uuid import UUID, uuid4
|
|
|
|
from app.flows.sync import lfx_id_for
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures" / "flows"
|
|
LANGFLOW_ID = "11111111-2222-4333-8444-555555555555"
|
|
|
|
|
|
def _export_doc(name="importiert"):
|
|
fixture = json.loads((FIXTURES / "simple_rule.json").read_text())
|
|
return {
|
|
"id": LANGFLOW_ID,
|
|
"name": name,
|
|
"description": "aus Langflow",
|
|
"endpoint_name": None,
|
|
"data": fixture["data"],
|
|
"tags": [],
|
|
"webhook": False,
|
|
"is_component": False,
|
|
}
|
|
|
|
|
|
async def test_import_creates_definition_version_and_deploys(client, lfx_server, override_langflow):
|
|
override_langflow(_export_doc())
|
|
response = await client.post(
|
|
"/api/flows/import",
|
|
json={"langflow_flow_id": LANGFLOW_ID, "author": "admin"},
|
|
)
|
|
assert response.status_code == 201, response.text
|
|
body = response.json()
|
|
assert body["definition"]["name"] == "importiert"
|
|
assert body["version"]["version_no"] == 1
|
|
assert body["version"]["author"] == "admin"
|
|
assert body["version"]["lfx_flow_id"] == lfx_id_for(UUID(body["definition"]["id"]), 1)
|
|
assert body["version"]["deployed_at"] is not None
|
|
assert body["version"]["langflow_json"]["data"]["nodes"]
|
|
|
|
# Imported flow actually runs on LFX.
|
|
definition_id = body["definition"]["id"]
|
|
response = await client.post(f"/api/flows/{definition_id}/run", json={"input": {"betrag": 10}})
|
|
assert response.status_code == 200, response.text
|
|
assert response.json()["status"] == "completed"
|
|
|
|
|
|
async def test_import_same_content_is_idempotent(client, lfx_server, override_langflow):
|
|
override_langflow(_export_doc())
|
|
first = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
second = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
assert first.status_code == 201
|
|
assert second.status_code == 201
|
|
assert first.json()["definition"]["id"] == second.json()["definition"]["id"]
|
|
# Unchanged content creates no new version.
|
|
assert second.json()["version"]["version_no"] == 1
|
|
|
|
|
|
async def test_import_changed_content_bumps_version(client, lfx_server, override_langflow):
|
|
override_langflow(_export_doc())
|
|
first = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
assert first.status_code == 201
|
|
changed = _export_doc()
|
|
changed["description"] = "neue Beschreibung"
|
|
override_langflow(changed)
|
|
second = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
assert second.status_code == 201
|
|
assert second.json()["version"]["version_no"] == 2
|
|
|
|
|
|
async def test_import_writes_canonical_file(
|
|
client, lfx_server, override_langflow, tmp_path, monkeypatch
|
|
):
|
|
from app.settings import settings
|
|
|
|
monkeypatch.setattr(settings, "flows_dir", str(tmp_path))
|
|
override_langflow(_export_doc())
|
|
response = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
assert response.status_code == 201, response.text
|
|
written = tmp_path / "importiert.json"
|
|
assert written.is_file()
|
|
assert json.loads(written.read_text())["name"] == "importiert"
|
|
|
|
|
|
async def test_import_with_explicit_name(client, lfx_server, override_langflow):
|
|
override_langflow(_export_doc(name="langflow-name"))
|
|
response = await client.post(
|
|
"/api/flows/import",
|
|
json={"langflow_flow_id": LANGFLOW_ID, "name": "wunschname"},
|
|
)
|
|
assert response.status_code == 201, response.text
|
|
assert response.json()["definition"]["name"] == "wunschname"
|
|
|
|
|
|
async def test_import_without_deploy(client, override_langflow):
|
|
override_langflow(_export_doc())
|
|
response = await client.post(
|
|
"/api/flows/import",
|
|
json={"langflow_flow_id": LANGFLOW_ID, "deploy": False},
|
|
)
|
|
assert response.status_code == 201, response.text
|
|
body = response.json()
|
|
assert body["version"]["lfx_flow_id"] is None
|
|
assert body["version"]["deployed_at"] is None
|
|
|
|
|
|
async def test_import_langflow_not_found(client, override_langflow):
|
|
override_langflow(status=404)
|
|
response = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
|
|
assert response.status_code == 404
|
|
|
|
|
|
async def test_import_langflow_unreachable(client, override_langflow):
|
|
override_langflow(status=0)
|
|
response = await client.post("/api/flows/import", json={"langflow_flow_id": str(uuid4())})
|
|
assert response.status_code == 503
|
|
|
|
|
|
async def test_list_langflow_flows(client, override_langflow):
|
|
override_langflow(_export_doc())
|
|
response = await client.get("/api/flows/langflow/available")
|
|
assert response.status_code == 200
|
|
assert response.json() == [{"id": "fake-1", "name": "fake"}]
|