"""设置 API 集成测试 - 测试 /api/settings 接口""" import pytest class TestSettingsAPI: """测试设置相关 API""" @pytest.mark.asyncio async def test_get_settings(self, client): """测试 GET /api/settings""" response = await client.get("/api/settings") assert response.status_code == 200 data = response.json() assert data["code"] == 200 assert "crawl_timeout" in data["data"] assert "validation_timeout" in data["data"] assert "auto_validate" in data["data"] @pytest.mark.asyncio async def test_get_settings_structure(self, client): """测试 GET /api/settings 返回结构""" response = await client.get("/api/settings") data = response.json()["data"] # 验证所有预期的设置项 expected_keys = [ "crawl_timeout", "validation_timeout", "max_retries", "default_concurrency", "min_proxy_score", "proxy_expiry_days", "auto_validate", "validate_interval_minutes", ] for key in expected_keys: assert key in data, f"缺少设置项: {key}" @pytest.mark.asyncio async def test_save_settings(self, client): """测试 POST /api/settings""" settings = { "crawl_timeout": 45, "validation_timeout": 15, "max_retries": 5, "default_concurrency": 100, "min_proxy_score": 10, "proxy_expiry_days": 14, "auto_validate": True, "validate_interval_minutes": 60, } response = await client.post("/api/settings", json=settings) assert response.status_code == 200 data = response.json() assert data["code"] == 200 # 验证返回的数据与提交的一致 for key, value in settings.items(): assert data["data"][key] == value @pytest.mark.asyncio async def test_save_settings_partial(self, client): """测试 POST /api/settings - 部分更新(实际上会替换所有)""" # 先获取当前设置 response = await client.get("/api/settings") current_settings = response.json()["data"] # 修改部分设置 new_settings = current_settings.copy() new_settings["crawl_timeout"] = 60 new_settings["auto_validate"] = False response = await client.post("/api/settings", json=new_settings) assert response.status_code == 200 data = response.json() assert data["data"]["crawl_timeout"] == 60 assert data["data"]["auto_validate"] is False @pytest.mark.asyncio async def test_save_settings_validation_error(self, client): """测试 POST /api/settings - 验证错误""" # crawl_timeout 必须在 5-120 之间 invalid_settings = { "crawl_timeout": 200, # 超出范围 "validation_timeout": 10, "max_retries": 3, "default_concurrency": 50, "min_proxy_score": 0, "proxy_expiry_days": 7, "auto_validate": True, "validate_interval_minutes": 30, } response = await client.post("/api/settings", json=invalid_settings) assert response.status_code == 422 # 验证错误 @pytest.mark.asyncio async def test_save_settings_invalid_type(self, client): """测试 POST /api/settings - 无效类型""" invalid_settings = { "crawl_timeout": "invalid", # 应该是整数 "validation_timeout": 10, "max_retries": 3, "default_concurrency": 50, "min_proxy_score": 0, "proxy_expiry_days": 7, "auto_validate": True, "validate_interval_minutes": 30, } response = await client.post("/api/settings", json=invalid_settings) assert response.status_code == 422 @pytest.mark.asyncio async def test_settings_roundtrip(self, client): """测试设置读写一致性""" # 生成随机但有效的设置 import random test_settings = { "crawl_timeout": random.randint(10, 60), "validation_timeout": random.randint(5, 30), "max_retries": random.randint(1, 5), "default_concurrency": random.randint(20, 100), "min_proxy_score": random.randint(0, 50), "proxy_expiry_days": random.randint(1, 14), "auto_validate": random.choice([True, False]), "validate_interval_minutes": random.randint(10, 120), } # 写入设置 response = await client.post("/api/settings", json=test_settings) assert response.status_code == 200 # 读取设置 response = await client.get("/api/settings") saved_settings = response.json()["data"] # 验证一致性 for key, value in test_settings.items(): assert saved_settings[key] == value, f"设置项 {key} 不一致" @pytest.mark.asyncio async def test_settings_roundtrip_with_validation_targets(self, client): """测试设置读写一致性 - 包含数组类型的 validation_targets""" test_settings = { "crawl_timeout": 30, "validation_timeout": 10, "max_retries": 3, "default_concurrency": 50, "min_proxy_score": 0, "proxy_expiry_days": 7, "auto_validate": True, "validate_interval_minutes": 30, "validation_targets": [ "http://example.com/1", "https://example.com/2", ], } # 写入设置 response = await client.post("/api/settings", json=test_settings) assert response.status_code == 200 data = response.json() assert data["data"]["validation_targets"] == test_settings["validation_targets"] # 读取设置 response = await client.get("/api/settings") saved_settings = response.json()["data"] assert saved_settings["validation_targets"] == test_settings["validation_targets"] @pytest.mark.asyncio async def test_save_settings_empty_validation_targets(self, client): """测试保存空的 validation_targets""" response = await client.get("/api/settings") current_settings = response.json()["data"] new_settings = current_settings.copy() new_settings["validation_targets"] = [] response = await client.post("/api/settings", json=new_settings) assert response.status_code == 200 data = response.json() assert data["data"]["validation_targets"] == [] # 读取确认 response = await client.get("/api/settings") saved_settings = response.json()["data"] assert saved_settings["validation_targets"] == []