Migrate all repos into monorepo context folders

Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
2026-06-30 20:39:52 +02:00
parent 2f2b295531
commit a5f8fb49ab
1717 changed files with 447332 additions and 0 deletions
@@ -0,0 +1,365 @@
"""Unit tests for the new capacity full-text DB methods on TrinoClient.
Covers single-row and batch variants for capacity description,
certificates, and references including the LEFT JOIN on
`teamlandkarte_v_partners_latest`.
"""
from __future__ import annotations
import re
import pytest
from teamlandkarte_mcp.database.trino_client import TrinoClient
class _FakeCursor:
"""Minimal cursor double recording executes and returning canned rows."""
def __init__(self, rows: list[tuple] | None = None) -> None:
self.executed: list[tuple[str, tuple[object, ...] | None]] = []
self._rows: list[tuple] = rows or []
def execute(self, sql: str, params=None) -> None: # noqa: ANN001
if params is None:
params_tuple: tuple[object, ...] | None = None
elif isinstance(params, tuple):
params_tuple = params
else:
params_tuple = tuple(params)
self.executed.append((sql, params_tuple))
def fetchone(self):
return self._rows[0] if self._rows else None
def fetchall(self):
return list(self._rows)
class _FakeCursorContext:
def __init__(self, cursor: _FakeCursor):
self._cursor = cursor
def __enter__(self) -> _FakeCursor:
return self._cursor
def __exit__(self, exc_type, exc, tb) -> None: # noqa: ANN001
return None
class _FakeConfig:
host = "x"
port = 1
username = "u"
password = "p"
http_scheme = "http"
verify_ssl = False
catalog = "c"
schema = "s"
pool_size = 1
def _mk_client(cur: _FakeCursor) -> TrinoClient:
client = TrinoClient(_FakeConfig())
client._cursor = lambda: _FakeCursorContext(cur) # type: ignore[method-assign]
return client
def _norm_sql(sql: str) -> str:
return re.sub(r"\s+", " ", sql).strip()
def _assert_select_only(sql: str) -> None:
upper = sql.strip().upper()
assert upper.startswith("SELECT"), f"expected SELECT, got: {sql!r}"
for kw in ("INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "TRUNCATE"):
assert kw not in upper, f"unexpected write keyword {kw} in SQL: {sql!r}"
# ---------------------------------------------------------------------------
# Single-row methods
# ---------------------------------------------------------------------------
def test_get_capacity_description_one_query_select_only_and_trims() -> None:
cur = _FakeCursor(rows=[(" hello world ",)])
c = _mk_client(cur)
out = c.get_capacity_description(42)
assert len(cur.executed) == 1, "exactly one SQL query expected"
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacities_latest" in sql_n
assert "WHERE id = ?" in sql_n
assert params == (42,)
assert out == "hello world"
def test_get_capacity_description_null_returns_none() -> None:
cur = _FakeCursor(rows=[(None,)])
c = _mk_client(cur)
assert c.get_capacity_description(1) is None
def test_get_capacity_description_whitespace_returns_none() -> None:
cur = _FakeCursor(rows=[(" \t ",)])
c = _mk_client(cur)
assert c.get_capacity_description(1) is None
def test_get_capacity_description_no_row_returns_none() -> None:
cur = _FakeCursor(rows=[])
c = _mk_client(cur)
assert c.get_capacity_description(99) is None
def test_get_capacity_certificates_one_query_filters_empty() -> None:
cur = _FakeCursor(
rows=[
("ISTQB Foundation",),
("",),
(" ",),
(None,),
("PMP ",),
]
)
c = _mk_client(cur)
out = c.get_capacity_certificates(7)
assert len(cur.executed) == 1
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacity_certificates_latest" in sql_n
assert "WHERE capacity_id = ?" in sql_n
assert params == (7,)
assert out == ["ISTQB Foundation", "PMP"]
def test_get_capacity_certificates_no_rows_returns_empty_list() -> None:
cur = _FakeCursor(rows=[])
c = _mk_client(cur)
assert c.get_capacity_certificates(123) == []
assert len(cur.executed) == 1
def test_get_capacity_references_single_query_includes_partner_left_join() -> None:
cur = _FakeCursor(
rows=[
("Project Alpha", "Acme GmbH"),
("Project Beta", ""), # NULL partner_id → COALESCE → ""
]
)
c = _mk_client(cur)
out = c.get_capacity_references(11)
assert len(cur.executed) == 1, "partner LEFT JOIN must be in the same query"
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacity_references_latest" in sql_n
assert "LEFT JOIN teamlandkarte_v_partners_latest" in sql_n
assert "r.partner_id = p.id" in sql_n
assert "WHERE r.capacity_id = ?" in sql_n
assert params == (11,)
assert out == [
{"projects": "Project Alpha", "partner_name": "Acme GmbH"},
{"projects": "Project Beta", "partner_name": ""},
]
def test_get_capacity_references_filters_empty_projects_keeps_empty_partner() -> None:
cur = _FakeCursor(
rows=[
("", "Acme GmbH"), # empty projects → drop
(" ", "X"), # whitespace only → drop
(None, "Y"), # non-string → drop
("Migration", ""), # empty partner is allowed
]
)
c = _mk_client(cur)
out = c.get_capacity_references(11)
assert out == [{"projects": "Migration", "partner_name": ""}]
def test_get_capacity_references_partner_name_none_normalizes_to_empty() -> None:
"""Defensive: if the driver returns None for partner_name, treat as ''."""
cur = _FakeCursor(rows=[("Project Alpha", None)])
c = _mk_client(cur)
out = c.get_capacity_references(11)
assert out == [{"projects": "Project Alpha", "partner_name": ""}]
# ---------------------------------------------------------------------------
# Batch variants
# ---------------------------------------------------------------------------
def test_batch_get_capacity_descriptions_empty_input_returns_empty_no_sql() -> None:
cur = _FakeCursor(rows=[])
c = _mk_client(cur)
out = c.batch_get_capacity_descriptions([])
assert out == {}
assert cur.executed == []
def test_batch_get_capacity_descriptions_one_query_groups_and_defaults() -> None:
cur = _FakeCursor(
rows=[
(1, " desc one "),
(2, None),
(3, " "),
]
)
c = _mk_client(cur)
out = c.batch_get_capacity_descriptions([1, 2, 3, 4])
assert len(cur.executed) == 1
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacities_latest" in sql_n
assert "WHERE id IN (?, ?, ?, ?)" in sql_n
assert params == (1, 2, 3, 4)
assert out == {"1": "desc one", "2": None, "3": None, "4": None}
def test_batch_get_capacity_certificates_empty_input_returns_empty_no_sql() -> None:
cur = _FakeCursor(rows=[])
c = _mk_client(cur)
out = c.batch_get_capacity_certificates([])
assert out == {}
assert cur.executed == []
def test_batch_get_capacity_certificates_groups_n_to_1_and_defaults() -> None:
cur = _FakeCursor(
rows=[
(1, "ISTQB"),
(1, " PMP "),
(1, ""), # filtered
(2, "AWS Solutions Architect"),
(1, None), # filtered
]
)
c = _mk_client(cur)
out = c.batch_get_capacity_certificates([1, 2, 3])
assert len(cur.executed) == 1
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacity_certificates_latest" in sql_n
assert "WHERE capacity_id IN (?, ?, ?)" in sql_n
assert params == (1, 2, 3)
assert out == {
"1": ["ISTQB", "PMP"],
"2": ["AWS Solutions Architect"],
"3": [], # default for missing id
}
def test_batch_get_capacity_references_empty_input_returns_empty_no_sql() -> None:
cur = _FakeCursor(rows=[])
c = _mk_client(cur)
out = c.batch_get_capacity_references([])
assert out == {}
assert cur.executed == []
def test_batch_get_capacity_references_partner_join_same_statement_and_groups() -> None:
cur = _FakeCursor(
rows=[
(1, "Project Alpha", "Acme GmbH"),
(1, "Project Beta", ""), # NULL partner_id → kept with empty partner
(2, "Migration", "BetaCorp"),
(1, " ", "X"), # filtered (empty projects)
(1, None, "Y"), # filtered (non-string projects)
]
)
c = _mk_client(cur)
out = c.batch_get_capacity_references([1, 2, 3])
assert len(cur.executed) == 1, (
"partner LEFT JOIN must be part of the same single batch query"
)
sql, params = cur.executed[0]
sql_n = _norm_sql(sql)
_assert_select_only(sql)
assert "FROM teamlandkarte_v_capacity_references_latest" in sql_n
assert "LEFT JOIN teamlandkarte_v_partners_latest" in sql_n
assert "r.partner_id = p.id" in sql_n
assert "WHERE r.capacity_id IN (?, ?, ?)" in sql_n
assert params == (1, 2, 3)
assert out == {
"1": [
{"projects": "Project Alpha", "partner_name": "Acme GmbH"},
{"projects": "Project Beta", "partner_name": ""},
],
"2": [{"projects": "Migration", "partner_name": "BetaCorp"}],
"3": [],
}
def test_batch_get_capacity_references_partner_name_none_normalizes_to_empty() -> None:
"""Defensive: driver returns None for partner_name → treated as ''."""
cur = _FakeCursor(rows=[(1, "Project Alpha", None)])
c = _mk_client(cur)
out = c.batch_get_capacity_references([1])
assert out == {
"1": [{"projects": "Project Alpha", "partner_name": ""}],
}
# ---------------------------------------------------------------------------
# SELECT-only guard parametric coverage
# ---------------------------------------------------------------------------
@pytest.mark.parametrize(
"method,args,rows",
[
("get_capacity_description", (1,), [("x",)]),
("get_capacity_certificates", (1,), [("x",)]),
("get_capacity_references", (1,), [("x", "")]),
("batch_get_capacity_descriptions", ([1, 2],), [(1, "x")]),
("batch_get_capacity_certificates", ([1, 2],), [(1, "x")]),
("batch_get_capacity_references", ([1, 2],), [(1, "x", "")]),
],
)
def test_capacity_fulltext_methods_emit_select_only(
method: str, args: tuple, rows: list[tuple]
) -> None:
cur = _FakeCursor(rows=rows)
c = _mk_client(cur)
getattr(c, method)(*args)
assert cur.executed, f"{method} should have executed a query"
assert len(cur.executed) == 1, f"{method} should issue exactly one query"
sql, _params = cur.executed[0]
_assert_select_only(sql)