"""Unit tests for the capacity details enrichment feature. Tests verify that get_capacity_details correctly displays description, references, and certificates sections with proper formatting and ordering. """ from __future__ import annotations from datetime import date import pytest from teamlandkarte_mcp.mcp_server import build_server from teamlandkarte_mcp.models import Capacity, Task class _FakeDB: """Fake DB client for testing get_capacity_details enrichment.""" def __init__( self, caps: list[Capacity], *, description: str | None = None, references: list[dict] | None = None, certificates: list[str] | None = None, ) -> None: self._caps = caps self._description = description self._references = references if references is not None else [] self._certificates = certificates if certificates is not None else [] def test_connection(self) -> None: return def get_table_columns(self, table: str) -> list[str]: if table == "teamlandkarte_v_capacity_roles_latest": return ["name", "active", "staffing_board_relevant"] if table == "teamlandkarte_v_capacities_latest": return ["creation_date"] if table == "teamlandkarte_v_teams_latest": return [ "team_id", "ouid", "about_us", "offerings", "interests", "focus_name", ] if table == "teamlandkarte_v_teammeter_organizational_units_latest": return ["id", "name"] if table == "teamlandkarte_v_teammeter_team_competences_latest": return ["ouid", "competence_id", "top_competency"] if table == "teamlandkarte_v_team_references_latest": return ["ouid", "partner_id", "projects"] return [] def get_all_role_names(self) -> list[str]: return ["Cloud Engineer"] def get_all_competence_names(self) -> list[str]: return ["AWS"] def get_open_tasks(self, limit: int = 20) -> list[Task]: return [] def get_task_by_id(self, task_id: str): return None def get_task_by_name(self, name: str): return None def get_all_capacities_with_competences(self) -> list[Capacity]: return list(self._caps) def get_recent_free_capacities(self, limit: int = 20) -> list[Capacity]: return list(self._caps)[:limit] def get_capacity_by_id(self, capacity_id: int | str) -> Capacity | None: cid = int(capacity_id) for c in self._caps: if int(c.id) == cid: return c return None def get_capacity_description(self, capacity_id: int | str) -> str | None: return self._description def get_capacity_references(self, capacity_id: int | str) -> list[dict]: return self._references def get_capacity_certificates(self, capacity_id: int | str) -> list[str]: return self._certificates def _make_config(tmp_path) -> str: """Write a minimal config.toml and return its path.""" cfg = tmp_path / "config.toml" cfg.write_text( """ [database] host='x' port=1 username='u' password='p' backend='trino' [matching] competence_weight=0.8 role_weight=0.2 require_confirmation=false [cache] db_ttl_hours=1 search_ttl_minutes=10 max_size=10 """.strip(), encoding="utf-8", ) return str(cfg) def _make_capacity(cap_id: int = 1) -> Capacity: return Capacity( id=cap_id, owner_name="Team Alpha", role_name="Cloud Engineer", role_level=None, begin_date=date(2026, 1, 1), end_date=date(2026, 6, 30), competences=["AWS", "Terraform"], ) # --------------------------------------------------------------------------- # 2.1 Test full data scenario # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_full_data_scenario(monkeypatch, tmp_path) -> None: """All enrichment sections are rendered with correct content and ordering.""" description = "Erfahrener Cloud-Architekt mit Fokus auf AWS-Infrastruktur." references = [ {"partner_name": "Deutsche Bahn", "projects": "Projekt Reiseportal, Projekt Fahrplan"}, {"partner_name": "", "projects": "Internes Migrationsprojekt"}, {"partner_name": "Siemens", "projects": "IoT Platform"}, ] certificates = [ "AWS Solutions Architect Professional", "Kubernetes Administrator (CKA)", ] cap = _make_capacity() fake_db = _FakeDB( [cap], description=description, references=references, certificates=certificates, ) import teamlandkarte_mcp.mcp_server as mod monkeypatch.setattr(mod, "create_db_client", lambda *_: fake_db) srv = build_server(_make_config(tmp_path)) content, structured = await srv.call_tool( "get_capacity_details", {"capacity_id": 1} ) out = (structured or {}).get("result") or getattr(content[0], "text", "") # Section headers present assert "## Beschreibung" in out assert "## Referenzen" in out assert "## Zertifizierungen" in out assert "## Next steps" in out # Description content assert description in out # References content: partner with name uses bold formatting assert "**Deutsche Bahn**: Projekt Reiseportal, Projekt Fahrplan" in out # Reference without partner_name shows only projects (no bold prefix) assert "- Internes Migrationsprojekt" in out assert "**Siemens**: IoT Platform" in out # Ensure the empty-partner reference does NOT have bold empty prefix assert "****:" not in out # Certificates content assert "- AWS Solutions Architect Professional" in out assert "- Kubernetes Administrator (CKA)" in out # Section ordering: Beschreibung < Referenzen < Zertifizierungen < Next steps idx_beschreibung = out.index("## Beschreibung") idx_referenzen = out.index("## Referenzen") idx_zertifizierungen = out.index("## Zertifizierungen") idx_next_steps = out.index("## Next steps") assert idx_beschreibung < idx_referenzen < idx_zertifizierungen < idx_next_steps # Capacity table appears before all enrichment sections assert "| capacity_id |" in out idx_table = out.index("| capacity_id |") assert idx_table < idx_beschreibung # --------------------------------------------------------------------------- # 2.2 Test empty-state scenario # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_empty_state_scenario(monkeypatch, tmp_path) -> None: """When all enrichment data is empty/None, (keine) placeholders appear.""" cap = _make_capacity() fake_db = _FakeDB( [cap], description=None, references=[], certificates=[], ) import teamlandkarte_mcp.mcp_server as mod monkeypatch.setattr(mod, "create_db_client", lambda *_: fake_db) srv = build_server(_make_config(tmp_path)) content, structured = await srv.call_tool( "get_capacity_details", {"capacity_id": 1} ) out = (structured or {}).get("result") or getattr(content[0], "text", "") # All three sections show (keine) placeholders assert "Beschreibung: (keine)" in out assert "Referenzen: (keine)" in out assert "Zertifizierungen: (keine)" in out # Section headers still present assert "## Beschreibung" in out assert "## Referenzen" in out assert "## Zertifizierungen" in out # --------------------------------------------------------------------------- # 2.3 Test capacity-not-found unchanged # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_capacity_not_found_unchanged(monkeypatch, tmp_path) -> None: """When capacity is not found, error message is returned without enrichment calls.""" fake_db = _FakeDB( [], # No capacities → get_capacity_by_id returns None description="Should not appear", references=[{"partner_name": "X", "projects": "Y"}], certificates=["Cert"], ) import teamlandkarte_mcp.mcp_server as mod monkeypatch.setattr(mod, "create_db_client", lambda *_: fake_db) srv = build_server(_make_config(tmp_path)) content, structured = await srv.call_tool( "get_capacity_details", {"capacity_id": 999} ) out = (structured or {}).get("result") or getattr(content[0], "text", "") # Returns the standard error message assert out == "Capacity not found: 999" # Enrichment data should NOT appear assert "## Beschreibung" not in out assert "## Referenzen" not in out assert "## Zertifizierungen" not in out assert "Should not appear" not in out