ForcePilot/backend/test/integration/channel/test_bindings_router.py
Kris 9e503becd3
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
feat(plugin): 实现完整的插件注册管理系统
新增了插件相关的完整领域模型、应用服务、基础设施实现,包括:
1. 插件状态、注册模式、来源等基础枚举和数据结构
2. 插件清单解析、发现、加载工具类
3. 插件注册表领域服务和内存存储实现
4. 插件相关的命令、查询、事件定义
5. 插件REST API接口和DTO映射
6. 集成了原有通道适配器到插件系统
7. 新增内置插件注册和自动发现能力
2026-05-31 16:44:13 +08:00

177 lines
6.2 KiB
Python

"""
Integration tests for channel bindings CRUD endpoints (/channel/bindings).
"""
from __future__ import annotations
import uuid
import pytest
pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
_BINDING_SEED = uuid.uuid4().hex[:8]
async def _create_binding(test_client, headers, *, channel_type="web", agent_config_id=1):
account_id = f"intg_test_{_BINDING_SEED}"
group_id = f"group_{_BINDING_SEED}"
response = await test_client.post(
"/channel/bindings",
json={
"channel_type": channel_type,
"account_id": account_id,
"group_id": group_id,
"agent_config_id": agent_config_id,
},
headers=headers,
)
return response
async def test_create_binding_returns_201(test_client, channel_auth_headers):
response = await _create_binding(test_client, channel_auth_headers)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 201, response.text
payload = response.json()
assert "id" in payload
assert payload["channel_type"] == "web"
assert payload["is_enabled"] is True
await test_client.delete(f"/channel/bindings/{payload['id']}", headers=channel_auth_headers)
async def test_create_binding_response_has_required_fields(test_client, channel_auth_headers):
response = await _create_binding(test_client, channel_auth_headers)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 201, response.text
payload = response.json()
for field in ("id", "channel_type", "account_id", "group_id", "agent_config_id", "is_enabled", "created_at"):
assert field in payload, f"missing field: {field}"
await test_client.delete(f"/channel/bindings/{payload['id']}", headers=channel_auth_headers)
async def test_create_binding_with_empty_channel_type_returns_422(test_client, channel_auth_headers):
response = await test_client.post(
"/channel/bindings",
json={
"channel_type": "",
"account_id": "test_acct",
"group_id": "",
"agent_config_id": 1,
},
headers=channel_auth_headers,
)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 422
async def test_create_binding_with_invalid_agent_config_id_returns_422(test_client, channel_auth_headers):
response = await test_client.post(
"/channel/bindings",
json={
"channel_type": "web",
"account_id": "test_acct",
"group_id": "",
"agent_config_id": 0,
},
headers=channel_auth_headers,
)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 422
async def test_list_bindings_returns_paginated_result(test_client, channel_auth_headers):
response = await test_client.get("/channel/bindings", headers=channel_auth_headers)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 200, response.text
payload = response.json()
assert "items" in payload
assert "meta" in payload
meta = payload["meta"]
for field in ("total", "offset", "limit"):
assert field in meta, f"missing meta field: {field}"
async def test_list_bindings_filter_by_channel_type(test_client, channel_auth_headers):
response = await test_client.get(
"/channel/bindings",
params={"channel_type": "web"},
headers=channel_auth_headers,
)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 200, response.text
payload = response.json()
for item in payload.get("items", []):
assert item["channel_type"] == "web"
async def test_list_bindings_pagination(test_client, channel_auth_headers):
response = await test_client.get(
"/channel/bindings",
params={"offset": 0, "limit": 1},
headers=channel_auth_headers,
)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 200, response.text
payload = response.json()
assert payload["meta"]["limit"] == 1
assert len(payload["items"]) <= 1
async def test_delete_binding_returns_ok(test_client, channel_auth_headers):
create_resp = await _create_binding(test_client, channel_auth_headers)
if create_resp.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert create_resp.status_code == 201, create_resp.text
binding_id = create_resp.json()["id"]
delete_resp = await test_client.delete(
f"/channel/bindings/{binding_id}",
headers=channel_auth_headers,
)
assert delete_resp.status_code == 200, delete_resp.text
assert delete_resp.json()["ok"] is True
async def test_delete_nonexistent_binding_returns_404(test_client, channel_auth_headers):
response = await test_client.delete(
"/channel/bindings/99999999",
headers=channel_auth_headers,
)
if response.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert response.status_code == 404
async def test_binding_full_lifecycle(test_client, channel_auth_headers):
create_resp = await _create_binding(test_client, channel_auth_headers)
if create_resp.status_code == 503:
pytest.skip("Channel gateway not initialized")
assert create_resp.status_code == 201, create_resp.text
binding = create_resp.json()
binding_id = binding["id"]
list_resp = await test_client.get("/channel/bindings", headers=channel_auth_headers)
assert list_resp.status_code == 200
ids = [b["id"] for b in list_resp.json()["items"]]
assert binding_id in ids
delete_resp = await test_client.delete(
f"/channel/bindings/{binding_id}",
headers=channel_auth_headers,
)
assert delete_resp.status_code == 200
list_resp2 = await test_client.get("/channel/bindings", headers=channel_auth_headers)
ids2 = [b["id"] for b in list_resp2.json()["items"]]
assert binding_id not in ids2