"""Tests for issue claim heartbeat leases (#268).""" from __future__ import annotations import sys import unittest from datetime import datetime, timedelta, timezone from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) import issue_claim_heartbeat as ich # noqa: E402 class TestHeartbeatFormatting(unittest.TestCase): def test_format_and_parse_roundtrip(self): body = ich.format_heartbeat_body( kind="claim", issue_number=268, branch="feat/issue-268-heartbeat-leases", phase="claimed", profile="prgs-author", next_action="implement module", ) parsed = ich.parse_heartbeat_comment(body) self.assertIsNotNone(parsed) assert parsed is not None self.assertEqual(parsed["issue_number"], 268) self.assertEqual(parsed["branch"], "feat/issue-268-heartbeat-leases") self.assertEqual(parsed["phase"], "claimed") class TestClaimClassification(unittest.TestCase): NOW = datetime(2026, 7, 7, 12, 0, tzinfo=timezone.utc) def _comment(self, *, minutes_ago: int, kind: str = "progress") -> dict: ts = (self.NOW - timedelta(minutes=minutes_ago)).isoformat() body = ich.format_heartbeat_body( kind=kind, issue_number=268, branch="feat/issue-268-heartbeat-leases", phase="implementation", profile="prgs-author", ) return {"id": 1, "body": body, "created_at": ts, "updated_at": ts} def test_active_claim_within_lease(self): issue = {"number": 268, "title": "t", "labels": [{"name": "status:in-progress"}]} result = ich.classify_issue_claim( issue=issue, comments=[self._comment(minutes_ago=5)], now=self.NOW, ) self.assertEqual(result["status"], "active") def test_stale_claim_without_branch(self): issue = {"number": 268, "title": "t", "labels": [{"name": "status:in-progress"}]} result = ich.classify_issue_claim( issue=issue, comments=[self._comment(minutes_ago=45)], now=self.NOW, ) self.assertEqual(result["status"], "stale") def test_reclaimable_after_sixty_minutes_without_branch(self): issue = {"number": 268, "title": "t", "labels": [{"name": "status:in-progress"}]} result = ich.classify_issue_claim( issue=issue, comments=[self._comment(minutes_ago=90)], now=self.NOW, ) self.assertEqual(result["status"], "reclaimable") def test_awaiting_review_when_open_pr_exists(self): issue = {"number": 268, "title": "t", "labels": [{"name": "status:in-progress"}]} open_prs = [ { "number": 400, "title": "feat", "body": "Closes #268", "head": {"ref": "feat/issue-268-heartbeat-leases"}, } ] result = ich.classify_issue_claim( issue=issue, comments=[self._comment(minutes_ago=120)], open_prs=open_prs, now=self.NOW, ) self.assertEqual(result["status"], "awaiting_review") def test_phantom_claim_without_heartbeat(self): issue = {"number": 268, "title": "t", "labels": [{"name": "status:in-progress"}]} result = ich.classify_issue_claim( issue=issue, comments=[{"id": 1, "body": "working on it"}], now=self.NOW, ) self.assertEqual(result["status"], "phantom") class TestInventory(unittest.TestCase): def test_build_cleanup_plan_flags_phantom(self): inventory = { "entries": [ {"issue_number": 1, "status": "phantom", "reasons": ["no heartbeat"]}, {"issue_number": 2, "status": "active", "reasons": []}, ] } plan = ich.build_cleanup_plan(inventory) self.assertEqual(len(plan), 1) self.assertEqual(plan[0]["issue_number"], 1) if __name__ == "__main__": unittest.main()