feat: release 1.1.0 with responsive task control
This commit is contained in:
1 parent
057f0c3050
commit
bfcd828fa8
37 files changed
+1601
-151
No files matched your search
@@ -6,6 +6,7 @@ import time
|
||||
from unittest.mock import AsyncMock
|
||||
import zipfile
|
||||
|
||||
from docx import Document
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from openpyxl import load_workbook
|
||||
@@ -124,6 +125,39 @@ def test_preferences_and_required_device(client):
|
||||
assert client.post("/api/automation/batches", json=payload(device_serial="")).status_code == 422
|
||||
|
||||
|
||||
def test_batch_delete_retains_executed_task_and_prevents_request_replay(client, isolated):
|
||||
created = client.post(
|
||||
"/api/automation/batches", json=payload(request_id="delete-example")
|
||||
).json()
|
||||
first, second = isolated.jobs(created["id"])
|
||||
isolated.save_job({**first, "status": "completed"})
|
||||
|
||||
response = client.delete(f"/api/automation/batches/{created['id']}")
|
||||
assert response.status_code == 200
|
||||
assert client.get(f"/api/automation/batches/{created['id']}").status_code == 404
|
||||
assert isolated.job(first["session_id"])["case"]["name"] == "用例甲"
|
||||
assert isolated.job(second["session_id"]) is None
|
||||
assert reports.session_report(first["session_id"])["name"] == "用例甲"
|
||||
assert (
|
||||
client.post(
|
||||
"/api/automation/batches", json=payload(request_id="delete-example")
|
||||
).status_code
|
||||
== 409
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("status", ["queued", "running", "task_paused", "resuming", "finalizing"])
|
||||
def test_batch_delete_rejects_active_jobs(client, isolated, status):
|
||||
batch = service.create_batch(payload())
|
||||
first = isolated.jobs(batch["id"])[0]
|
||||
isolated.save_job({**first, "status": status})
|
||||
|
||||
response = client.delete(f"/api/automation/batches/{batch['id']}")
|
||||
assert response.status_code == 409
|
||||
assert isolated.get("batch", batch["id"]) is not None
|
||||
assert len(isolated.jobs(batch["id"])) == 2
|
||||
|
||||
|
||||
def test_restart_never_repeats_started_work(isolated):
|
||||
batch = service.create_batch(payload())
|
||||
service.batch_action(batch["id"], "resume")
|
||||
@@ -243,6 +277,50 @@ def test_reports_do_not_execute_formulas_or_invent_pass(isolated):
|
||||
assert "未验证".encode() in doc.read("word/document.xml")
|
||||
|
||||
|
||||
def test_failed_report_exposes_logged_reason_and_formats_chinese_markdown(isolated):
|
||||
job = isolated.jobs(service.create_batch(payload())["id"])[0]
|
||||
isolated.save_job({**job, "status": "failed"})
|
||||
folder = reports.TRACES_PATH / job["session_id"]
|
||||
(folder / "notes").mkdir(parents=True)
|
||||
(folder / "stdout.log").write_text(
|
||||
"❌ [run] Error running automation: 模型连续 3 次未提供可执行的工具调用\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(folder / "notes" / "output.md").write_text(
|
||||
"## 结果\n- **网络**正常\n\n| 分类 | 状态 |\n| --- | --- |\n| 系统 | 未确认 |",
|
||||
encoding="utf-8",
|
||||
)
|
||||
report = reports.session_report(job["session_id"])
|
||||
assert "连续 3 次" in report["error"]
|
||||
assert report["verdict"] == "未验证(任务异常终止)"
|
||||
assert "abc123secret" not in reports.failure_reason(
|
||||
folder, "failed", "认证失败 OPENAI_API_KEY=abc123secret Authorization: Bearer abc123secret"
|
||||
)
|
||||
paths = reports.export_session(job["session_id"])
|
||||
doc = Document(next(path for path in paths if path.suffix == ".docx"))
|
||||
assert doc.styles["Normal"].font.name == "Microsoft YaHei"
|
||||
assert any("异常原因" in paragraph.text for paragraph in doc.paragraphs)
|
||||
assert any(
|
||||
run.bold and "网络" in run.text for paragraph in doc.paragraphs for run in paragraph.runs
|
||||
)
|
||||
assert any(
|
||||
cell.text == "分类" for table in doc.tables for row in table.rows for cell in row.cells
|
||||
)
|
||||
wb = load_workbook(next(path for path in paths if path.suffix == ".xlsx"))
|
||||
assert "连续 3 次" in wb["任务结果"]["B15"].value
|
||||
assert wb["结论"]["B2"].value == "结果"
|
||||
assert wb["结果表1"]["A2"].value == "系统"
|
||||
assert wb["执行证据"]["A1"].font.name == "微软雅黑"
|
||||
assert wb["执行证据"].page_setup.orientation == "landscape"
|
||||
assert reports.execution_result_label({"status": "dispatched"}) == "动作已发出(需核对截图)"
|
||||
assert reports.conclusion_rows("## 结果\n- **通过**检查\n```txt\n| 不是 | 表格 |\n```") == [
|
||||
("类型", "结论与发现"),
|
||||
("小节", "结果"),
|
||||
("要点", "通过检查"),
|
||||
("代码", "| 不是 | 表格 |"),
|
||||
]
|
||||
|
||||
|
||||
def test_task_material_zip_contains_ordered_evidence_and_reports(
|
||||
client, isolated, tmp_path, monkeypatch
|
||||
):
|
||||
|
||||
Reference in new issue
Block a user