"""边界情况测试""" import json import pytest def test_invalid_json_body(client, tmp_config): """无效 JSON 请求体""" resp = client.post( "/api/tasks", content="not json", headers={"Content-Type": "application/json"}, ) assert resp.status_code == 422 def test_missing_required_fields(client, tmp_config): """缺少必填字段""" resp = client.post("/api/tasks", json={"app_id": "1"}) assert resp.status_code == 422 def test_empty_app_id(client, tmp_config): """空 app_id""" resp = client.post("/api/tasks", json={ "app_id": "", "build_type": "Ad_Hoc", "scheme_id": "1", }) assert resp.status_code == 400 def test_server_name_with_special_chars(client, tmp_config): """服务器名称包含特殊字符""" resp = client.post("/api/config/servers", json={ "name": "环境/测试", "api": "https://test.com", }) assert resp.status_code == 200 def test_branch_name_with_slash(client, tmp_config): """分支名包含斜杠""" resp = client.post("/api/config/branches", json={"name": "feature/my-branch"}) assert resp.status_code == 200 assert "feature/my-branch" in client.get("/api/config/branches").json() def test_branch_name_with_space(client, tmp_config): """分支名包含空格(应被 trim)""" resp = client.post("/api/config/branches", json={"name": " "}) assert resp.status_code == 400 def test_config_backup_on_save(client, tmp_config): """保存配置时自动备份""" # 先写一次产生文件 client.put("/api/config", json={"apps": {}, "schemes": {}, "branches": ["main"]}) # 再写一次,应该产生 .bak 文件 client.put("/api/config", json={"apps": {"1": {"name": "test"}}, "schemes": {}, "branches": ["main"]}) backup = tmp_config.with_suffix(".json.bak") assert backup.exists() def test_sequential_config_writes(client, tmp_config): """顺序多次写入配置""" for i in range(5): resp = client.post("/api/config/branches", json={"name": f"branch-{i}"}) assert resp.status_code == 200 branches = client.get("/api/config/branches").json() for i in range(5): assert f"branch-{i}" in branches def test_task_status_filter(client, tmp_config): """按状态过滤任务""" from unittest.mock import patch, AsyncMock with patch("backend.services.build_queue.build_queue") as mock_queue: mock_queue.submit = AsyncMock() client.post("/api/tasks", json={ "app_id": "1", "build_type": "Ad_Hoc", "scheme_id": "1", }) # 过滤 pending resp = client.get("/api/tasks?status=pending") assert resp.status_code == 200 assert len(resp.json()) >= 1 # 过滤 running(应该没有) resp = client.get("/api/tasks?status=running") assert len(resp.json()) == 0 def test_task_pagination(client, tmp_config): """任务分页""" from unittest.mock import patch, AsyncMock with patch("backend.services.build_queue.build_queue") as mock_queue: mock_queue.submit = AsyncMock() for _ in range(5): client.post("/api/tasks", json={ "app_id": "1", "build_type": "Ad_Hoc", "scheme_id": "1", }) resp = client.get("/api/tasks?limit=2&offset=0") assert len(resp.json()) == 2 resp = client.get("/api/tasks?limit=2&offset=2") assert len(resp.json()) == 2 def test_delete_server_not_in_use(client, tmp_config): """删除未被使用的服务器""" # 先添加一个不被使用的服务器 client.post("/api/config/servers", json={"name": "临时环境", "api": "https://tmp.com"}) resp = client.delete("/api/config/servers/临时环境") assert resp.status_code == 200 def test_update_full_config_replaces_all(client, tmp_config): """整体替换配置""" new_config = { "apps": {"99": {"name": "新App"}}, "schemes": {}, "servers": {}, "branches": ["release"], } resp = client.put("/api/config", json=new_config) assert resp.status_code == 200 config = client.get("/api/config").json() assert "99" in config["apps"] assert config["branches"] == ["release"] def test_scheme_id_auto_increment(client, tmp_config): """Scheme ID 自动递增""" client.post("/api/config/schemes", json={"name": "sch2", "ossFloder": "f2"}) client.post("/api/config/schemes", json={"name": "sch3", "ossFloder": "f3"}) schemes = client.get("/api/config/schemes").json() assert "2" in schemes assert "3" in schemes def test_build_settings_validation(client, tmp_config): """打包设置更新""" # 更新为有效值 resp = client.put("/api/config/build", json={"max_concurrent_builds": 3}) assert resp.status_code == 200 assert client.get("/api/config/build").json()["max_concurrent_builds"] == 3 # 更新部分字段 resp = client.put("/api/config/build", json={"build_dir_retention_hours": 48}) assert resp.status_code == 200 settings = client.get("/api/config/build").json() assert settings["build_dir_retention_hours"] == 48 assert settings["max_concurrent_builds"] == 3 # 未修改的保持不变