Files
Orchestrator/shared/AI-Orchestrator/tests/test_reporter.py
T
ankn a5f8fb49ab 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.
2026-06-30 20:39:52 +02:00

191 lines
6.6 KiB
Python

"""Unit tests for the Summary Reporter module."""
from __future__ import annotations
from scripts.pat_manager.models import CheckResult, PatEntry, PatStatus, RotationResult
from scripts.pat_manager.reporter import SummaryReporter
def make_entry(service: str = "GitLab", token_name: str = "ci-token") -> PatEntry:
"""Helper to create a PatEntry for testing."""
return PatEntry(
service=service,
token_name=token_name,
expiry_date="2025-08-15",
renewal_method="auto" if service == "GitLab" else "manual",
)
def make_result(
service: str = "GitLab",
token_name: str = "ci-token",
status: PatStatus = PatStatus.HEALTHY,
days_remaining: int | None = 45,
error_message: str | None = None,
) -> CheckResult:
"""Helper to create a CheckResult for testing."""
entry = make_entry(service, token_name)
return CheckResult(
entry=entry,
status=status,
days_remaining=days_remaining,
error_message=error_message,
)
class TestSummaryReporter:
"""Tests for SummaryReporter.report()."""
def test_report_header(self) -> None:
"""Report starts with the expected header."""
reporter = SummaryReporter()
report = reporter.report([], [])
assert "=== PAT Lifecycle Check Summary ===" in report
def test_report_contains_table_headers(self) -> None:
"""Report contains column headers."""
reporter = SummaryReporter()
results = [make_result()]
report = reporter.report(results, [])
assert "Service" in report
assert "Token Name" in report
assert "Status" in report
assert "Details" in report
def test_report_one_healthy_pat(self) -> None:
"""Report shows healthy PAT with days remaining."""
reporter = SummaryReporter()
results = [make_result(days_remaining=45)]
report = reporter.report(results, [])
assert "GitLab" in report
assert "ci-token" in report
assert "healthy" in report
assert "45 days remaining" in report
def test_report_expiring_soon_pat(self) -> None:
"""Report shows expiring soon PAT with days remaining."""
reporter = SummaryReporter()
results = [
make_result(
service="Jira",
token_name="jira-api",
status=PatStatus.EXPIRING_SOON,
days_remaining=7,
)
]
report = reporter.report(results, [])
assert "Jira" in report
assert "jira-api" in report
assert "expiring soon" in report
assert "7 days remaining" in report
def test_report_expired_pat(self) -> None:
"""Report shows expired PAT with 0 days remaining."""
reporter = SummaryReporter()
results = [
make_result(
service="Confluence",
token_name="confluence-bot",
status=PatStatus.EXPIRED,
days_remaining=0,
)
]
report = reporter.report(results, [])
assert "Confluence" in report
assert "confluence-bot" in report
assert "expired" in report
assert "0 days remaining" in report
def test_report_check_failed_pat(self) -> None:
"""Report shows check failed PAT with error message."""
reporter = SummaryReporter()
results = [
make_result(
service="OrgMyLife",
token_name="orchestrator-key",
status=PatStatus.CHECK_FAILED,
days_remaining=None,
error_message="Connection timeout",
)
]
report = reporter.report(results, [])
assert "OrgMyLife" in report
assert "orchestrator-key" in report
assert "check failed" in report
assert "Connection timeout" in report
def test_report_multiple_pats(self) -> None:
"""Report contains one line per PAT."""
reporter = SummaryReporter()
results = [
make_result(service="GitLab", token_name="token-a", days_remaining=45),
make_result(
service="Jira",
token_name="token-b",
status=PatStatus.EXPIRING_SOON,
days_remaining=7,
),
make_result(
service="Confluence",
token_name="token-c",
status=PatStatus.EXPIRED,
days_remaining=0,
),
]
report = reporter.report(results, [])
assert "token-a" in report
assert "token-b" in report
assert "token-c" in report
def test_report_no_rotation_section_when_empty(self) -> None:
"""Report omits rotation section when no rotations occurred."""
reporter = SummaryReporter()
results = [make_result()]
report = reporter.report(results, [])
assert "Rotation Results" not in report
def test_report_includes_rotation_section(self) -> None:
"""Report includes rotation section with successful rotations."""
reporter = SummaryReporter()
entry = make_entry("GitLab", "ci-pipeline-token")
results = [make_result()]
rotations = [
RotationResult(
success=True,
new_token="glpat-new-value",
new_expiry_date="2025-08-01",
error_message=None,
entry=entry,
old_expiry_date="2025-07-01",
)
]
report = reporter.report(results, rotations)
assert "--- Rotation Results ---" in report
assert "GitLab/ci-pipeline-token" in report
assert "Rotated successfully" in report
assert "old: 2025-07-01" in report
assert "new: 2025-08-01" in report
def test_report_excludes_failed_rotations(self) -> None:
"""Report rotation section only shows successful rotations."""
reporter = SummaryReporter()
results = [make_result()]
rotations = [
RotationResult(
success=False,
new_token=None,
new_expiry_date=None,
error_message="Rotation failed",
entry=make_entry("GitLab", "failed-token"),
old_expiry_date="2025-07-01",
)
]
report = reporter.report(results, rotations)
assert "Rotation Results" not in report
def test_report_empty_results(self) -> None:
"""Report handles empty results list gracefully."""
reporter = SummaryReporter()
report = reporter.report([], [])
assert "=== PAT Lifecycle Check Summary ===" in report