新增了插件相关的完整领域模型、应用服务、基础设施实现,包括: 1. 插件状态、注册模式、来源等基础枚举和数据结构 2. 插件清单解析、发现、加载工具类 3. 插件注册表领域服务和内存存储实现 4. 插件相关的命令、查询、事件定义 5. 插件REST API接口和DTO映射 6. 集成了原有通道适配器到插件系统 7. 新增内置插件注册和自动发现能力
163 lines
6.0 KiB
Python
163 lines
6.0 KiB
Python
"""
|
|
Integration tests for channel plugin registry endpoints (/channel/plugins).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
|
|
|
|
|
|
async def test_list_plugins_returns_plugin_list(test_client, channel_auth_headers):
|
|
response = await test_client.get("/channel/plugins", 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 "plugins" in payload
|
|
assert "total" in payload
|
|
assert isinstance(payload["plugins"], list)
|
|
|
|
|
|
async def test_list_plugins_filter_by_status(test_client, channel_auth_headers):
|
|
response = await test_client.get(
|
|
"/channel/plugins",
|
|
params={"status": "activated"},
|
|
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 plugin in payload.get("plugins", []):
|
|
assert plugin["status"] == "activated"
|
|
|
|
|
|
async def test_list_plugins_filter_by_origin(test_client, channel_auth_headers):
|
|
response = await test_client.get(
|
|
"/channel/plugins",
|
|
params={"origin": "bundled"},
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 200, response.text
|
|
|
|
|
|
async def test_list_plugins_item_has_required_fields(test_client, channel_auth_headers):
|
|
response = await test_client.get("/channel/plugins", 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()
|
|
if not payload["plugins"]:
|
|
pytest.skip("No plugins registered")
|
|
plugin = payload["plugins"][0]
|
|
for field in ("plugin_id", "name", "version", "channel_type", "status", "source", "is_configured"):
|
|
assert field in plugin, f"missing field: {field}"
|
|
|
|
|
|
async def test_get_plugin_detail(test_client, channel_auth_headers):
|
|
list_resp = await test_client.get("/channel/plugins", headers=channel_auth_headers)
|
|
if list_resp.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
plugins = list_resp.json().get("plugins", [])
|
|
if not plugins:
|
|
pytest.skip("No plugins registered")
|
|
|
|
plugin_id = plugins[0]["plugin_id"]
|
|
detail_resp = await test_client.get(
|
|
f"/channel/plugins/{plugin_id}",
|
|
headers=channel_auth_headers,
|
|
)
|
|
assert detail_resp.status_code == 200, detail_resp.text
|
|
detail = detail_resp.json()
|
|
assert detail["plugin_id"] == plugin_id
|
|
for field in ("name", "version", "channel_type", "status", "capabilities", "config_schema"):
|
|
assert field in detail, f"missing detail field: {field}"
|
|
|
|
|
|
async def test_get_nonexistent_plugin_returns_404(test_client, channel_auth_headers):
|
|
response = await test_client.get(
|
|
"/channel/plugins/nonexistent_plugin_xyz",
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 404
|
|
|
|
|
|
async def test_get_plugin_manifest(test_client, channel_auth_headers):
|
|
list_resp = await test_client.get("/channel/plugins", headers=channel_auth_headers)
|
|
if list_resp.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
plugins = list_resp.json().get("plugins", [])
|
|
if not plugins:
|
|
pytest.skip("No plugins registered")
|
|
|
|
plugin_id = plugins[0]["plugin_id"]
|
|
manifest_resp = await test_client.get(
|
|
f"/channel/plugins/{plugin_id}/manifest",
|
|
headers=channel_auth_headers,
|
|
)
|
|
assert manifest_resp.status_code == 200, manifest_resp.text
|
|
|
|
|
|
async def test_get_nonexistent_plugin_manifest_returns_404(test_client, channel_auth_headers):
|
|
response = await test_client.get(
|
|
"/channel/plugins/nonexistent_plugin_xyz/manifest",
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 404
|
|
|
|
|
|
async def test_get_plugin_config_schema(test_client, channel_auth_headers):
|
|
list_resp = await test_client.get("/channel/plugins", headers=channel_auth_headers)
|
|
if list_resp.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
plugins = list_resp.json().get("plugins", [])
|
|
if not plugins:
|
|
pytest.skip("No plugins registered")
|
|
|
|
plugin_id = plugins[0]["plugin_id"]
|
|
schema_resp = await test_client.get(
|
|
f"/channel/plugins/{plugin_id}/config-schema",
|
|
headers=channel_auth_headers,
|
|
)
|
|
assert schema_resp.status_code == 200, schema_resp.text
|
|
assert "config_schema" in schema_resp.json()
|
|
|
|
|
|
async def test_activate_nonexistent_plugin_returns_404(test_client, channel_auth_headers):
|
|
response = await test_client.post(
|
|
"/channel/plugins/nonexistent_plugin_xyz/activate",
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 404
|
|
|
|
|
|
async def test_deactivate_nonexistent_plugin_returns_404(test_client, channel_auth_headers):
|
|
response = await test_client.post(
|
|
"/channel/plugins/nonexistent_plugin_xyz/deactivate",
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 404
|
|
|
|
|
|
async def test_reload_nonexistent_plugin_returns_404(test_client, channel_auth_headers):
|
|
response = await test_client.post(
|
|
"/channel/plugins/nonexistent_plugin_xyz/reload",
|
|
json={"force": False},
|
|
headers=channel_auth_headers,
|
|
)
|
|
if response.status_code == 503:
|
|
pytest.skip("Channel gateway not initialized")
|
|
assert response.status_code == 404
|