forked from Rockachopa/Timmy-time-dashboard
Wire orchestrator pipe into task runner + pipe-verifying integration tests (#134)
This commit is contained in:
committed by
GitHub
parent
d10cff333a
commit
87dc5eadfe
180
tests/integrations/test_paperclip_client.py
Normal file
180
tests/integrations/test_paperclip_client.py
Normal file
@@ -0,0 +1,180 @@
|
||||
"""Tests for the Paperclip API client."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from integrations.paperclip.client import PaperclipClient
|
||||
from integrations.paperclip.models import CreateIssueRequest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client():
|
||||
return PaperclipClient(base_url="http://fake:3100", api_key="test-key")
|
||||
|
||||
|
||||
# ── health ───────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_healthy_returns_true_on_success(client):
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value={"status": "ok"}):
|
||||
assert await client.healthy() is True
|
||||
|
||||
|
||||
async def test_healthy_returns_false_on_failure(client):
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=None):
|
||||
assert await client.healthy() is False
|
||||
|
||||
|
||||
# ── agents ───────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_list_agents_returns_list(client):
|
||||
raw = [{"id": "a1", "name": "Codex", "role": "engineer", "status": "active"}]
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
with patch("integrations.paperclip.client.settings") as mock_settings:
|
||||
mock_settings.paperclip_company_id = "comp-1"
|
||||
agents = await client.list_agents(company_id="comp-1")
|
||||
assert len(agents) == 1
|
||||
assert agents[0].name == "Codex"
|
||||
|
||||
|
||||
async def test_list_agents_graceful_on_none(client):
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=None):
|
||||
agents = await client.list_agents(company_id="comp-1")
|
||||
assert agents == []
|
||||
|
||||
|
||||
# ── issues ───────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_list_issues(client):
|
||||
raw = [{"id": "i1", "title": "Fix bug"}]
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
issues = await client.list_issues(company_id="comp-1")
|
||||
assert len(issues) == 1
|
||||
assert issues[0].title == "Fix bug"
|
||||
|
||||
|
||||
async def test_get_issue(client):
|
||||
raw = {"id": "i1", "title": "Fix bug", "description": "It's broken"}
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
issue = await client.get_issue("i1")
|
||||
assert issue is not None
|
||||
assert issue.id == "i1"
|
||||
|
||||
|
||||
async def test_get_issue_not_found(client):
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=None):
|
||||
issue = await client.get_issue("nonexistent")
|
||||
assert issue is None
|
||||
|
||||
|
||||
async def test_create_issue(client):
|
||||
raw = {"id": "i2", "title": "New feature"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
req = CreateIssueRequest(title="New feature")
|
||||
issue = await client.create_issue(req, company_id="comp-1")
|
||||
assert issue is not None
|
||||
assert issue.id == "i2"
|
||||
|
||||
|
||||
async def test_create_issue_no_company_id(client):
|
||||
with patch("integrations.paperclip.client.settings") as mock_settings:
|
||||
mock_settings.paperclip_company_id = ""
|
||||
issue = await client.create_issue(
|
||||
CreateIssueRequest(title="Test"),
|
||||
)
|
||||
assert issue is None
|
||||
|
||||
|
||||
async def test_delete_issue(client):
|
||||
with patch.object(client, "_delete", new_callable=AsyncMock, return_value=True):
|
||||
result = await client.delete_issue("i1")
|
||||
assert result is True
|
||||
|
||||
|
||||
# ── comments ─────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_add_comment(client):
|
||||
raw = {"id": "c1", "issue_id": "i1", "content": "Done"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
comment = await client.add_comment("i1", "Done")
|
||||
assert comment is not None
|
||||
assert comment.content == "Done"
|
||||
|
||||
|
||||
async def test_list_comments(client):
|
||||
raw = [{"id": "c1", "issue_id": "i1", "content": "LGTM"}]
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
comments = await client.list_comments("i1")
|
||||
assert len(comments) == 1
|
||||
|
||||
|
||||
# ── goals ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_list_goals(client):
|
||||
raw = [{"id": "g1", "title": "Ship MVP"}]
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
goals = await client.list_goals(company_id="comp-1")
|
||||
assert len(goals) == 1
|
||||
assert goals[0].title == "Ship MVP"
|
||||
|
||||
|
||||
async def test_create_goal(client):
|
||||
raw = {"id": "g2", "title": "Scale to 1000 users"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
goal = await client.create_goal("Scale to 1000 users", company_id="comp-1")
|
||||
assert goal is not None
|
||||
|
||||
|
||||
# ── wake agent ───────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_wake_agent(client):
|
||||
raw = {"status": "queued"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
result = await client.wake_agent("a1", issue_id="i1")
|
||||
assert result == {"status": "queued"}
|
||||
|
||||
|
||||
async def test_wake_agent_failure(client):
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=None):
|
||||
result = await client.wake_agent("a1")
|
||||
assert result is None
|
||||
|
||||
|
||||
# ── approvals ────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_approve(client):
|
||||
raw = {"status": "approved"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
result = await client.approve("ap1", comment="LGTM")
|
||||
assert result is not None
|
||||
|
||||
|
||||
async def test_reject(client):
|
||||
raw = {"status": "rejected"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
result = await client.reject("ap1", comment="Needs work")
|
||||
assert result is not None
|
||||
|
||||
|
||||
# ── heartbeat runs ───────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
async def test_list_heartbeat_runs(client):
|
||||
raw = [{"id": "r1", "agent_id": "a1", "status": "running"}]
|
||||
with patch.object(client, "_get", new_callable=AsyncMock, return_value=raw):
|
||||
runs = await client.list_heartbeat_runs(company_id="comp-1")
|
||||
assert len(runs) == 1
|
||||
|
||||
|
||||
async def test_cancel_run(client):
|
||||
raw = {"status": "cancelled"}
|
||||
with patch.object(client, "_post", new_callable=AsyncMock, return_value=raw):
|
||||
result = await client.cancel_run("r1")
|
||||
assert result is not None
|
||||
Reference in New Issue
Block a user