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,329 @@
"""Unit tests for the PAT Manager alert sender module."""
from __future__ import annotations
import pytest
import respx
from httpx import Response
from scripts.pat_manager.alerter import AlertSender
from scripts.pat_manager.errors import AlertError
from scripts.pat_manager.models import (
AlertChannel,
AlertResult,
CheckResult,
PatEntry,
PatStatus,
)
@pytest.fixture
def expiring_result() -> CheckResult:
"""A CheckResult for a Jira token expiring in 7 days."""
return CheckResult(
entry=PatEntry(
service="Jira",
token_name="jira-api-access",
expiry_date="2025-08-01",
renewal_method="manual",
),
status=PatStatus.EXPIRING_SOON,
days_remaining=7,
error_message=None,
)
@pytest.fixture
def expired_result() -> CheckResult:
"""A CheckResult for an expired Confluence token."""
return CheckResult(
entry=PatEntry(
service="Confluence",
token_name="confluence-bot",
expiry_date="2025-06-01",
renewal_method="manual",
),
status=PatStatus.EXPIRED,
days_remaining=0,
error_message=None,
)
@pytest.fixture
def orgmylife_config() -> dict:
"""Config for OrgMyLife alert channel."""
return {
"orgmylife_url": "https://orgmylife.app",
"orgmylife_api_key": "test-api-key-123",
}
@pytest.fixture
def email_config() -> dict:
"""Config for email alert channel."""
return {
"smtp_host": "smtp.example.com",
"smtp_port": "587",
"smtp_user": "user@example.com",
"smtp_pass": "password123",
"alert_email_to": "admin@example.com",
}
class TestAlertSenderInit:
"""Tests for AlertSender initialization."""
def test_orgmylife_channel(self, orgmylife_config: dict) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
assert sender.channel == AlertChannel.ORGMYLIFE
assert sender.config == orgmylife_config
def test_email_channel(self, email_config: dict) -> None:
sender = AlertSender(AlertChannel.EMAIL, email_config)
assert sender.channel == AlertChannel.EMAIL
assert sender.config == email_config
class TestBuildTaskTitle:
"""Tests for task title formatting."""
def test_title_format(self, expiring_result: CheckResult, orgmylife_config: dict) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
title = sender._build_task_title(expiring_result)
assert title == "[PAT Renewal] Jira - jira-api-access"
def test_title_contains_service_and_token(
self, expired_result: CheckResult, orgmylife_config: dict
) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
title = sender._build_task_title(expired_result)
assert "Confluence" in title
assert "confluence-bot" in title
assert title == "[PAT Renewal] Confluence - confluence-bot"
class TestBuildTaskDescription:
"""Tests for task description formatting."""
def test_expiring_description(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
desc = sender._build_task_description(expiring_result)
assert "7 days" in desc
assert "2025-08-01" in desc
assert "Manual renewal required" in desc
assert "Jira" in desc
assert "jira-api-access" in desc
def test_expired_description(
self, expired_result: CheckResult, orgmylife_config: dict
) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
desc = sender._build_task_description(expired_result)
assert "0 days remaining" in desc
assert "Token has expired" in desc
assert "Manual renewal required" in desc
class TestSendAlertOrgMyLife:
"""Tests for OrgMyLife alert sending."""
@pytest.mark.asyncio
@respx.mock
async def test_successful_task_creation(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
# Mock: no existing tasks
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(200, json=[])
)
# Mock: successful task creation
respx.post("https://orgmylife.app/api/tasks").mock(
return_value=Response(201, json={"id": 1, "title": "[PAT Renewal] Jira - jira-api-access"})
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
result = await sender.send_alert(expiring_result)
assert result.sent is True
assert result.channel == AlertChannel.ORGMYLIFE
assert result.error_message is None
@pytest.mark.asyncio
@respx.mock
async def test_skips_when_existing_task(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
# Mock: existing task found
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(
200,
json=[{"title": "[PAT Renewal] Jira - jira-api-access", "status": "open"}],
)
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
result = await sender.send_alert(expiring_result)
assert result.sent is False
assert result.channel == AlertChannel.ORGMYLIFE
assert result.error_message is None
@pytest.mark.asyncio
@respx.mock
async def test_raises_alert_error_on_failure(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
# Mock: no existing tasks
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(200, json=[])
)
# Mock: task creation fails
respx.post("https://orgmylife.app/api/tasks").mock(
return_value=Response(500, json={"error": "Internal Server Error"})
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
with pytest.raises(AlertError) as exc_info:
await sender.send_alert(expiring_result)
assert "orgmylife" in exc_info.value.channel
assert "500" in exc_info.value.reason
@pytest.mark.asyncio
@respx.mock
async def test_api_key_header_sent(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
# Mock: no existing tasks
get_route = respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(200, json=[])
)
# Mock: successful task creation
post_route = respx.post("https://orgmylife.app/api/tasks").mock(
return_value=Response(201, json={"id": 1})
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
await sender.send_alert(expiring_result)
# Verify API key was sent
assert get_route.calls[0].request.headers["X-API-Key"] == "test-api-key-123"
assert post_route.calls[0].request.headers["X-API-Key"] == "test-api-key-123"
class TestCheckExistingTask:
"""Tests for idempotent alerting via check_existing_task."""
@pytest.mark.asyncio
@respx.mock
async def test_returns_true_when_task_exists(self, orgmylife_config: dict) -> None:
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(
200,
json=[{"title": "[PAT Renewal] Jira - jira-api-access", "status": "open"}],
)
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
exists = await sender.check_existing_task("Jira", "jira-api-access", "2025-08-01")
assert exists is True
@pytest.mark.asyncio
@respx.mock
async def test_returns_false_when_no_task(self, orgmylife_config: dict) -> None:
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(200, json=[])
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
exists = await sender.check_existing_task("Jira", "jira-api-access", "2025-08-01")
assert exists is False
@pytest.mark.asyncio
@respx.mock
async def test_returns_false_on_api_error(self, orgmylife_config: dict) -> None:
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(500, json={"error": "Server Error"})
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
exists = await sender.check_existing_task("Jira", "jira-api-access", "2025-08-01")
assert exists is False
@pytest.mark.asyncio
@respx.mock
async def test_handles_wrapped_response(self, orgmylife_config: dict) -> None:
"""Test handling of paginated/wrapped API response."""
respx.get("https://orgmylife.app/api/tasks").mock(
return_value=Response(
200,
json={
"tasks": [
{"title": "[PAT Renewal] Jira - jira-api-access", "status": "open"}
]
},
)
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
exists = await sender.check_existing_task("Jira", "jira-api-access", "2025-08-01")
assert exists is True
class TestSendAlertEmail:
"""Tests for email alert sending."""
@pytest.mark.asyncio
async def test_raises_on_missing_smtp_config(
self, expiring_result: CheckResult
) -> None:
sender = AlertSender(AlertChannel.EMAIL, {})
with pytest.raises(AlertError) as exc_info:
await sender.send_alert(expiring_result)
assert "email" in exc_info.value.channel
@pytest.mark.asyncio
async def test_raises_on_missing_email_to(
self, expiring_result: CheckResult
) -> None:
config = {"smtp_host": "smtp.example.com"}
sender = AlertSender(AlertChannel.EMAIL, config)
with pytest.raises(AlertError) as exc_info:
await sender.send_alert(expiring_result)
assert "email" in exc_info.value.channel
class TestDaysRemainingInAlert:
"""Tests for days remaining in alert messages."""
def test_expired_shows_zero_days(
self, expired_result: CheckResult, orgmylife_config: dict
) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
desc = sender._build_task_description(expired_result)
assert "0 days remaining" in desc
def test_expiring_shows_correct_days(
self, expiring_result: CheckResult, orgmylife_config: dict
) -> None:
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
desc = sender._build_task_description(expiring_result)
assert "7 days" in desc
def test_none_days_remaining_treated_as_zero(self, orgmylife_config: dict) -> None:
result = CheckResult(
entry=PatEntry(
service="OrgMyLife",
token_name="test-token",
expiry_date=None,
renewal_method="manual",
),
status=PatStatus.EXPIRED,
days_remaining=None,
error_message=None,
)
sender = AlertSender(AlertChannel.ORGMYLIFE, orgmylife_config)
desc = sender._build_task_description(result)
assert "0 days remaining" in desc