Files
plane-gptproto-integration/ai-agent/tests/test_data_issues.py
T
carlandCursor 0136c15274 Initial commit: Plane 自部署与 gptproto AI 集成
包含本地/远程部署脚本、AI Agent 服务、Dashboard 与 QA 验证。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 11:37:41 +08:00

112 lines
3.3 KiB
Python

import httpx
import pytest
import respx
ISSUES_RESPONSE = [
{
"id": "issue-1",
"name": "修复登录 Bug",
"state": "state-uuid-1",
"priority": "urgent",
"assignees": ["mem-1"],
"start_date": "2026-04-01",
"due_date": "2026-04-10",
},
{
"id": "issue-2",
"name": "优化首页性能",
"state": "state-uuid-2",
"priority": "medium",
"assignees": ["mem-2"],
"start_date": None,
"due_date": None,
},
]
@pytest.mark.asyncio
@respx.mock
async def test_issues_returns_list(client):
respx.get(
"http://api:8000/api/v1/workspaces/ws-demo/projects/proj-123/issues/"
).mock(return_value=httpx.Response(200, json={"results": ISSUES_RESPONSE}))
resp = await client.get(
"/data/issues",
params={"workspace_slug": "ws-demo", "project_id": "proj-123"},
)
assert resp.status_code == 200
body = resp.json()
assert isinstance(body, list)
assert len(body) == 2
@pytest.mark.asyncio
@respx.mock
async def test_issues_fields(client):
respx.get(
"http://api:8000/api/v1/workspaces/ws-demo/projects/proj-123/issues/"
).mock(return_value=httpx.Response(200, json={"results": ISSUES_RESPONSE}))
resp = await client.get(
"/data/issues",
params={"workspace_slug": "ws-demo", "project_id": "proj-123"},
)
issue = resp.json()[0]
for field in ("id", "name", "state", "priority", "assignees"):
assert field in issue
@pytest.mark.asyncio
@respx.mock
async def test_issues_forwards_assignee_filter(client):
route = respx.get(
"http://api:8000/api/v1/workspaces/ws-demo/projects/proj-123/issues/"
).mock(return_value=httpx.Response(200, json={"results": [ISSUES_RESPONSE[0]]}))
resp = await client.get(
"/data/issues",
params={
"workspace_slug": "ws-demo",
"project_id": "proj-123",
"assignee_id": "mem-1",
},
)
assert resp.status_code == 200
assert route.called
qs = str(route.calls[0].request.url)
assert "assignee" in qs or "mem-1" in qs
@pytest.mark.asyncio
@respx.mock
async def test_issues_sends_api_key(client):
route = respx.get(
"http://api:8000/api/v1/workspaces/ws-demo/projects/proj-123/issues/"
).mock(return_value=httpx.Response(200, json={"results": ISSUES_RESPONSE}))
await client.get(
"/data/issues",
params={"workspace_slug": "ws-demo", "project_id": "proj-123"},
)
assert route.calls[0].request.headers.get("x-api-key") == "test-plane-token"
@pytest.mark.asyncio
@respx.mock
async def test_issues_plane_error_returns_502(client):
respx.get(
"http://api:8000/api/v1/workspaces/ws-demo/projects/proj-123/issues/"
).mock(return_value=httpx.Response(404, json={"detail": "not found"}))
resp = await client.get(
"/data/issues",
params={"workspace_slug": "ws-demo", "project_id": "proj-123"},
)
assert resp.status_code == 502
@pytest.mark.asyncio
async def test_issues_missing_params_returns_422(client):
resp = await client.get("/data/issues", params={"workspace_slug": "ws-demo"})
assert resp.status_code == 422
resp2 = await client.get("/data/issues", params={"project_id": "proj-123"})
assert resp2.status_code == 422