forked from Rockachopa/Timmy-time-dashboard
115 lines
3.2 KiB
Python
115 lines
3.2 KiB
Python
"""Unit tests for timmy.vassal.dispatch — routing and label helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from timmy.vassal.backlog import AgentTarget, TriagedIssue
|
|
from timmy.vassal.dispatch import (
|
|
DispatchRecord,
|
|
clear_dispatch_registry,
|
|
get_dispatch_registry,
|
|
)
|
|
|
|
|
|
def _make_triaged(
|
|
number: int,
|
|
title: str,
|
|
agent: AgentTarget,
|
|
priority: int = 50,
|
|
) -> TriagedIssue:
|
|
return TriagedIssue(
|
|
number=number,
|
|
title=title,
|
|
body="",
|
|
agent_target=agent,
|
|
priority_score=priority,
|
|
rationale="test rationale",
|
|
url=f"http://gitea/issues/{number}",
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Registry helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_registry_starts_empty():
|
|
clear_dispatch_registry()
|
|
assert get_dispatch_registry() == {}
|
|
|
|
|
|
def test_registry_returns_copy():
|
|
clear_dispatch_registry()
|
|
reg = get_dispatch_registry()
|
|
reg[999] = None # type: ignore[assignment]
|
|
assert 999 not in get_dispatch_registry()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# dispatch_issue — Timmy self-dispatch (no Gitea required)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_dispatch_timmy_self_no_gitea():
|
|
"""Timmy self-dispatch records without hitting Gitea."""
|
|
clear_dispatch_registry()
|
|
|
|
issue = _make_triaged(1, "Fix docs typo", AgentTarget.TIMMY)
|
|
from timmy.vassal.dispatch import dispatch_issue
|
|
|
|
record = await dispatch_issue(issue)
|
|
|
|
assert isinstance(record, DispatchRecord)
|
|
assert record.issue_number == 1
|
|
assert record.agent == AgentTarget.TIMMY
|
|
assert 1 in get_dispatch_registry()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_dispatch_claude_no_gitea_token():
|
|
"""Claude dispatch gracefully degrades when Gitea token is absent."""
|
|
clear_dispatch_registry()
|
|
|
|
issue = _make_triaged(2, "Refactor auth", AgentTarget.CLAUDE)
|
|
from timmy.vassal.dispatch import dispatch_issue
|
|
|
|
record = await dispatch_issue(issue)
|
|
|
|
assert record.issue_number == 2
|
|
assert record.agent == AgentTarget.CLAUDE
|
|
# label/comment not applied — no token
|
|
assert record.label_applied is False
|
|
assert 2 in get_dispatch_registry()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_dispatch_kimi_no_gitea_token():
|
|
clear_dispatch_registry()
|
|
|
|
issue = _make_triaged(3, "Research embeddings", AgentTarget.KIMI)
|
|
from timmy.vassal.dispatch import dispatch_issue
|
|
|
|
record = await dispatch_issue(issue)
|
|
|
|
assert record.agent == AgentTarget.KIMI
|
|
assert record.label_applied is False
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# DispatchRecord fields
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_dispatch_record_defaults():
|
|
r = DispatchRecord(
|
|
issue_number=5,
|
|
issue_title="Test issue",
|
|
agent=AgentTarget.TIMMY,
|
|
rationale="because",
|
|
)
|
|
assert r.label_applied is False
|
|
assert r.comment_posted is False
|
|
assert r.dispatched_at # has a timestamp
|