178 lines
6.8 KiB
Python
178 lines
6.8 KiB
Python
"""插件 API 集成测试 - 测试 /api/plugins/* 所有接口"""
|
|
import pytest
|
|
|
|
|
|
class TestPluginsAPI:
|
|
"""测试插件相关 API"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_plugins(self, client):
|
|
"""测试 GET /api/plugins"""
|
|
response = await client.get("/api/plugins")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert "plugins" in data["data"]
|
|
assert isinstance(data["data"]["plugins"], list)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_plugins_structure(self, client):
|
|
"""测试 GET /api/plugins 返回结构"""
|
|
response = await client.get("/api/plugins")
|
|
data = response.json()
|
|
if data["data"]["plugins"]:
|
|
plugin = data["data"]["plugins"][0]
|
|
assert "id" in plugin
|
|
assert "name" in plugin
|
|
assert "display_name" in plugin
|
|
assert "description" in plugin
|
|
assert "enabled" in plugin
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_plugin_enable(self, client):
|
|
"""测试 PUT /api/plugins/{id}/toggle - 启用"""
|
|
# 先获取一个插件 ID
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.put(f"/api/plugins/{plugin_id}/toggle", json={"enabled": True})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert data["data"]["enabled"] is True
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_plugin_disable(self, client):
|
|
"""测试 PUT /api/plugins/{id}/toggle - 禁用"""
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.put(f"/api/plugins/{plugin_id}/toggle", json={"enabled": False})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert data["data"]["enabled"] is False
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_plugin_missing_enabled(self, client):
|
|
"""测试 PUT /api/plugins/{id}/toggle - 缺少 enabled 参数"""
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.put(f"/api/plugins/{plugin_id}/toggle", json={})
|
|
# Pydantic 验证缺失必填字段返回 422
|
|
assert response.status_code == 422
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_toggle_nonexistent_plugin(self, client):
|
|
"""测试 PUT /api/plugins/{id}/toggle - 不存在的插件"""
|
|
response = await client.put("/api/plugins/nonexistent_plugin/toggle", json={"enabled": True})
|
|
assert response.status_code == 404
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_plugin_config(self, client):
|
|
"""测试 GET /api/plugins/{id}/config"""
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.get(f"/api/plugins/{plugin_id}/config")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert "config" in data["data"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_nonexistent_plugin_config(self, client):
|
|
"""测试 GET /api/plugins/{id}/config - 不存在的插件"""
|
|
response = await client.get("/api/plugins/nonexistent_plugin/config")
|
|
assert response.status_code == 404
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_plugin_config(self, client):
|
|
"""测试 POST /api/plugins/{id}/config"""
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.post(
|
|
f"/api/plugins/{plugin_id}/config",
|
|
json={"config": {"max_pages": 3}}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_crawl_plugin(self, client):
|
|
"""测试 POST /api/plugins/{id}/crawl - 异步任务模式"""
|
|
import asyncio
|
|
response = await client.get("/api/plugins")
|
|
plugins = response.json()["data"]["plugins"]
|
|
if not plugins:
|
|
pytest.skip("没有可用的插件")
|
|
|
|
plugin_id = plugins[0]["id"]
|
|
response = await client.post(f"/api/plugins/{plugin_id}/crawl")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert "task_id" in data["data"]
|
|
|
|
task_id = data["data"]["task_id"]
|
|
# 轮询任务状态
|
|
task_data = None
|
|
for _ in range(10):
|
|
await asyncio.sleep(0.3)
|
|
res = await client.get(f"/api/tasks/{task_id}")
|
|
assert res.status_code == 200
|
|
task_data = res.json()["data"]
|
|
if task_data["status"] in ("completed", "failed", "cancelled"):
|
|
break
|
|
|
|
assert task_data is not None
|
|
assert task_data["status"] in ("completed", "cancelled")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_crawl_nonexistent_plugin(self, client):
|
|
"""测试 POST /api/plugins/{id}/crawl - 不存在的插件"""
|
|
response = await client.post("/api/plugins/nonexistent_plugin/crawl")
|
|
assert response.status_code == 404
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_crawl_all_plugins(self, client):
|
|
"""测试 POST /api/plugins/crawl-all - 异步任务模式"""
|
|
import asyncio
|
|
response = await client.post("/api/plugins/crawl-all")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["code"] == 200
|
|
assert "task_id" in data["data"]
|
|
|
|
task_id = data["data"]["task_id"]
|
|
# 轮询任务状态
|
|
task_data = None
|
|
for _ in range(10):
|
|
await asyncio.sleep(0.3)
|
|
res = await client.get(f"/api/tasks/{task_id}")
|
|
assert res.status_code == 200
|
|
task_data = res.json()["data"]
|
|
if task_data["status"] in ("completed", "failed", "cancelled"):
|
|
break
|
|
|
|
assert task_data is not None
|
|
assert task_data["status"] in ("completed", "cancelled")
|