kirche-einfach/backend/tests/test_form_components.py

104 lines
3.6 KiB
Python

"""Phase 2 tests: kirche CustomInput* library + intake fixture flow."""
import json
import sys
from pathlib import Path
from lfx.custom import Component
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(REPO_ROOT / "backend" / "components"))
from kirche.form_inputs import CustomInputForm # noqa: E402
FIXTURES = Path(__file__).parent / "fixtures" / "flows"
FORM_FIELDS = [
"full_name",
"notes",
"password",
"age",
"amount",
"newsletter",
"department",
"topics",
"satisfaction",
"attachment",
]
def test_component_contract():
assert issubclass(CustomInputForm, Component)
assert CustomInputForm.display_name.startswith("CustomInput")
inputs = {i.name: i for i in CustomInputForm.inputs}
# Ten form fields plus the hidden run-envelope plumbing input.
assert sorted(n for n in inputs if n != "form_values") == sorted(FORM_FIELDS)
assert inputs["form_values"].show is False
outputs = {o.name: o for o in CustomInputForm.outputs}
assert set(outputs) == {"form_data"}
def test_collect_merges_submitted_values_over_defaults():
from lfx.schema.message import Message
form = CustomInputForm()
default = json.loads(form.collect().text)
assert default["full_name"] == ""
assert default["department"] == "Music"
assert isinstance(form.collect(), Message)
form.form_values = json.dumps({"full_name": "Maria", "age": 41})
merged = json.loads(form.collect().text)
assert merged["full_name"] == "Maria"
assert merged["age"] == 41
assert merged["department"] == "Music" # default kept
# Run envelope shape {"payload": {...}} unwraps like the other components.
form.form_values = json.dumps({"payload": {"notes": "hi"}})
assert json.loads(form.collect().text)["notes"] == "hi"
form.form_values = "not json"
assert json.loads(form.collect().text)["full_name"] == ""
def test_intake_fixture_shape():
doc = json.loads((FIXTURES / "intake_form.json").read_text())
nodes = {n["id"]: n for n in doc["data"]["nodes"]}
form = nodes["CustomInputForm-intake"]
assert form["data"]["type"] == "CustomInputForm"
assert form["data"]["node"]["display_name"].startswith("CustomInput")
template = form["data"]["node"]["template"]
for field in FORM_FIELDS:
assert field in template, field
assert template["form_values"]["show"] is False
assert len(template["code"]["value"]) > 200
edges = {(e["source"], e["target"]) for e in doc["data"]["edges"]}
assert ("ChatInput-entry", "CustomInputForm-intake") in edges
assert ("CustomInputForm-intake", "ChatOutput-collected") in edges
async def test_intake_deploy_and_run_with_values(client, lfx_server):
doc = json.loads((FIXTURES / "intake_form.json").read_text())
created = await client.post("/api/flows", json={"name": "intake-e2e"})
assert created.status_code == 201, created.text
flow_id = created.json()["id"]
version = await client.post(
f"/api/flows/{flow_id}/versions",
json={"langflow_json": doc, "author": "test"},
)
assert version.status_code == 201, version.text
deployed = await client.post(f"/api/flows/{flow_id}/versions/1/deploy")
assert deployed.status_code == 200, deployed.text
run = await client.post(
f"/api/flows/{flow_id}/run",
json={"input": {"full_name": "Maria Muster", "age": 41}},
)
assert run.status_code == 200, run.text
assert run.json()["status"] == "completed"
result = json.loads(run.json()["output"]["result"])
assert result["full_name"] == "Maria Muster"
assert result["age"] == 41
assert result["department"] == "Music" # default preserved