From 53b5de28bc6e487008945e758f5a918934ce3bf182336f7368535c82398bbecd Mon Sep 17 00:00:00 2001 From: tlg Date: Thu, 9 Jul 2026 15:49:08 +0200 Subject: [PATCH] test(projekt-matching): e2e helper scripts; component gates verified Co-Authored-By: Claude Fable 5 --- projekt-matching/tests/e2e/check_state.py | 28 +++++++++++++++++++++++ projekt-matching/tests/e2e/cleanup_crm.py | 19 +++++++++++++++ projekt-matching/tests/e2e/run_flow2.py | 20 ++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100755 projekt-matching/tests/e2e/check_state.py create mode 100755 projekt-matching/tests/e2e/cleanup_crm.py create mode 100755 projekt-matching/tests/e2e/run_flow2.py diff --git a/projekt-matching/tests/e2e/check_state.py b/projekt-matching/tests/e2e/check_state.py new file mode 100755 index 0000000..4c8dd33 --- /dev/null +++ b/projekt-matching/tests/e2e/check_state.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +"""Report current system state: CRM hits for a token, INBOX/Trash mails.""" +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) +from projektmatch import mailer # noqa: E402 +from projektmatch.espocrm import EspoClient # noqa: E402 + +token = sys.argv[1] if len(sys.argv) > 1 else "" +espo = EspoClient(os.environ["PM_ESPO_BASE"], os.environ["PM_ESPO_API_KEY"]) +if token: + hits = espo.search("Opportunity", "contains", "cProjektlink", token, + select="name,cProjektlink") + print(f"CRM hits for '{token}': {len(hits)}") + for h in hits: + print(f" {h['id']} {h['name']}") +box = mailer.MailBox("chancen@destengs.com", os.environ["PM_IMAP_PASSWORD"]) +for folder in ("INBOX", box.trash_folder()): + box.conn.select(folder) + typ, data = box.conn.uid("SEARCH", None, "ALL") + uids = data[0].split() if data and data[0] else [] + print(f"{folder}: {len(uids)} mails") + for uid in uids[-8:]: + typ, d = box.conn.uid("FETCH", uid.decode(), + "(BODY.PEEK[HEADER.FIELDS (SUBJECT)])") + print(" ", d[0][1].decode(errors="replace").strip()) +box.close() diff --git a/projekt-matching/tests/e2e/cleanup_crm.py b/projekt-matching/tests/e2e/cleanup_crm.py new file mode 100755 index 0000000..37c20d1 --- /dev/null +++ b/projekt-matching/tests/e2e/cleanup_crm.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +"""Delete test opportunities whose cProjektlink contains a token.""" +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) +from projektmatch.espocrm import EspoClient # noqa: E402 + +TOKENS = sys.argv[1:] or [ + "python-entwickler-fuer-eine-ki-anwendung", + "test-engineer-m-w-d-3020995", + "nproj/3020338", "nproj/3020995"] +espo = EspoClient(os.environ["PM_ESPO_BASE"], os.environ["PM_ESPO_API_KEY"]) +for token in TOKENS: + for hit in espo.search("Opportunity", "contains", "cProjektlink", token, + select="name,cProjektlink", max_size=100): + espo.delete("Opportunity", hit["id"]) + print(f"deleted {hit['id']} {hit['name']}") +print("cleanup done") diff --git a/projekt-matching/tests/e2e/run_flow2.py b/projekt-matching/tests/e2e/run_flow2.py new file mode 100755 index 0000000..18f3d70 --- /dev/null +++ b/projekt-matching/tests/e2e/run_flow2.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Run Flow 2 directly via the Langflow run API from the host.""" +import json +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) +from projektmatch.config import Cfg # noqa: E402 +from projektmatch.ingest import dispatch_flow2 # noqa: E402 + +env = dict(line.split("=", 1) for line in open( + os.path.expanduser("~/.config/projekt-matching/env")) + if "=" in line.strip()) +cfg = Cfg(flow2_id=env["FLOW2_ID"].strip(), + langflow_api_key=env["LANGFLOW_API_KEY"].strip(), + langflow_base="http://127.0.0.1:8090") +result = dispatch_flow2(cfg, {"canonical": sys.argv[1], + "title": sys.argv[2] if len(sys.argv) > 2 + else "Test"}) +print(json.dumps(result, indent=2, ensure_ascii=False))