kirche-einfach/backend/tests/test_deploy.py

137 lines
5.2 KiB
Python

"""Step 4 tests: Langflow import pipeline (Langflow faked, LFX real)."""
import json
from uuid import UUID, uuid4
import pytest
from app.flows.sync import lfx_id_for
from .conftest import langflow_export_doc
LANGFLOW_ID = "11111111-2222-4333-8444-555555555555"
def _export_doc(name="importiert"):
"""Alias of the shared conftest helper (kept for call-site stability)."""
return langflow_export_doc(name, LANGFLOW_ID)
async def test_import_creates_definition_version_and_deploys(
client, login, lfx_server, override_langflow
):
override_langflow(_export_doc())
await login()
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, login, lfx_server, override_langflow):
override_langflow(_export_doc())
await login()
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, login, lfx_server, override_langflow):
override_langflow(_export_doc())
await login()
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, login, lfx_server, override_langflow, tmp_path, monkeypatch
):
from app.settings import settings
monkeypatch.setattr(settings, "flows_dir", str(tmp_path))
override_langflow(_export_doc())
await login()
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, login, lfx_server, override_langflow):
override_langflow(_export_doc(name="langflow-name"))
await login()
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_with_implicit_name_uses_langflow_name(client, login, override_langflow):
override_langflow(_export_doc(name="langflow-name"))
await login()
response = await client.post("/api/flows/import", json={"langflow_flow_id": LANGFLOW_ID})
assert response.status_code == 201, response.text
assert response.json()["definition"]["name"] == "langflow-name"
async def test_import_without_deploy(client, login, override_langflow):
override_langflow(_export_doc())
await login()
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
@pytest.mark.parametrize(
("fake_status", "expected_status"),
[(404, 404), (0, 503)],
)
async def test_import_langflow_failures(
client, login, override_langflow, fake_status, expected_status
):
"""Langflow 404/unreachable maps to 404/503 (parametrized)."""
override_langflow(status=fake_status)
await login()
target = LANGFLOW_ID if fake_status == 404 else str(uuid4())
response = await client.post("/api/flows/import", json={"langflow_flow_id": target})
assert response.status_code == expected_status
async def test_list_langflow_flows(client, login, override_langflow):
override_langflow(_export_doc())
await login()
response = await client.get("/api/flows/langflow/available")
assert response.status_code == 200
assert response.json() == [{"id": "fake-1", "name": "fake"}]