"""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"}]