Files
ProxyPool/tests/integration/test_plugins_api.py

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")