feat(trading): 清空购物车落步骤证据,补空车/有商品两场景测试
- clear_cart 返回清理后 cart 页最终 HTML(best-effort,抓取失败不掩盖清理结果)
- runner step 0 落 00-cart-clear.{html,meta.json} 并登记 evidence_index,
证据先于闸门判断落盘(清理未净被拦时这份现场就是排查依据);
仍是本机卫生步骤:不上报 gateway、不记 order_events
- /api/cart/clear 响应不携带 html(路由显式挑字段,与 cart_add 同风格)
- 单测:fake page 覆盖空车/有商品/HTML 抓取失败;runner 层覆盖证据落盘
与闸门拦截场景
- 真账号复验 scripts/verify_cart_clear.py:空车 removed=0/count=0;
加购 1 件后 clear removed=1/count=0,status 复核 101
This commit is contained in:
@@ -13,6 +13,7 @@ evidence store / site,覆盖 §6 主循环的分支:
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
@@ -559,6 +560,62 @@ async def test_execute_blocks_when_clear_count_unknown(
|
||||
assert "未清空" in terminal["detail"]
|
||||
|
||||
|
||||
async def test_clear_cart_step_writes_evidence_but_no_gateway_report(
|
||||
runner: WorkerRunner, evidence: EvidenceStore
|
||||
):
|
||||
"""step 0 落本地证据:清理后的页面 HTML 与 meta.json 在盘上,但不回报 gateway
|
||||
|
||||
clear_cart 返回的 html 是清理结束后的 cart 页现场,meta 记 removed_count /
|
||||
cart_count;它仍是本机卫生步骤——evidence_index 可翻查,gateway 收不到
|
||||
这一步的 evidence_ref。
|
||||
"""
|
||||
async def _clear(): # noqa: ANN001
|
||||
return {"removed_count": 1, "cart_count": 0, "html": "<html>cart</html>"}
|
||||
|
||||
async def _noop(task): # noqa: ANN001
|
||||
return None
|
||||
|
||||
async def _unimplemented(task): # noqa: ANN001
|
||||
# 流程走到 enter_checkout 为止:step 0 的证据此时已经落盘
|
||||
raise NotImplementedError("模拟:enter_checkout 未实现,到此为止")
|
||||
|
||||
runner._site.clear_cart = _clear # type: ignore[assignment]
|
||||
runner._site.add_to_cart = _noop # type: ignore[assignment]
|
||||
runner._site.verify_cart = _noop # type: ignore[assignment]
|
||||
runner._site.enter_checkout = _unimplemented # type: ignore[assignment]
|
||||
|
||||
await runner.handle(_make_task(task_id="t1"))
|
||||
|
||||
step_dir = evidence.step_dir("t1")
|
||||
html_text = (step_dir / "00-cart-clear.html").read_text(encoding="utf-8")
|
||||
assert html_text == "<html>cart</html>"
|
||||
meta = json.loads((step_dir / "00-cart-clear.meta.json").read_text(encoding="utf-8"))
|
||||
assert meta == {"step": "cart-clear", "removed_count": 1, "cart_count": 0}
|
||||
# 本机卫生步骤:gateway 的任何 report 都不携带 step-0 的 evidence_ref
|
||||
gateway: FakeGateway = runner._gateway_for_test # type: ignore[attr-defined]
|
||||
assert all(r["evidence_ref"] != "t1/00-cart-clear" for r in gateway.reports)
|
||||
|
||||
|
||||
async def test_clear_cart_evidence_written_when_guard_blocks(
|
||||
runner: WorkerRunner, evidence: EvidenceStore
|
||||
):
|
||||
"""闸门拦截(清理后 cart_count 非 0)时 step-0 证据同样已落盘
|
||||
|
||||
被拦转 needs_human 时这份现场就是排查依据——证据先于闸门判断落盘。
|
||||
"""
|
||||
async def _clear(): # noqa: ANN001
|
||||
return {"removed_count": 2, "cart_count": 2, "html": "<html>leftover</html>"}
|
||||
|
||||
runner._site.clear_cart = _clear # type: ignore[assignment]
|
||||
|
||||
await runner.handle(_make_task(task_id="t1"))
|
||||
|
||||
step_dir = evidence.step_dir("t1")
|
||||
assert (step_dir / "00-cart-clear.html").exists()
|
||||
meta = json.loads((step_dir / "00-cart-clear.meta.json").read_text(encoding="utf-8"))
|
||||
assert meta["cart_count"] == 2
|
||||
|
||||
|
||||
# ---- 证据在 report 之前落盘(§9 第 11 条)----
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user