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:
2026-08-17 08:32:11 +08:00
parent daa5555fd4
commit 086ab82614
6 changed files with 340 additions and 11 deletions
+17 -3
View File
@@ -1010,8 +1010,11 @@ class SiteInteractor:
- 若 SPA 把按钮渲染在 iframe 里,selector 失败需实测后调整
- Rakuten cart item 卡片无 data-testid,本方法不依赖 DOM 结构定位
返回 {removed_count, cart_count};cart_count=-1 表示末尾 count API 调用失败
(空车属正常结果返回 0,见 _query_cart_count 的 status=101 处理)。
返回 {removed_count, cart_count, html};cart_count=-1 表示末尾 count API
调用失败(空车属正常结果返回 0,见 _query_cart_count 的 status=101 处理)。
html 是清理结束后 cart 页的最终渲染结果,供调用方落证据排查——清理没跑干净
被 runner 闸门拦下时这份现场就是排查依据;HTTP /api/cart/clear 入口的响应
模型不携带它。
"""
async with self._lock:
await self._auth_session.require_logged_in("rakuten")
@@ -1019,6 +1022,7 @@ class SiteInteractor:
page = await self._context.new_page()
removed = 0
html = ""
try:
await page.goto(_CART_PAGE, wait_until="domcontentloaded", timeout=30_000)
await self._wait_cart_rendered(page, label="clear_cart")
@@ -1047,6 +1051,16 @@ class SiteInteractor:
"clear_cart 触发安全上限 %s,可能有删除失败或 SPA 异常",
_CLEAR_CART_MAX_ITER,
)
# 清理结束后的最终页面留给调用方落证据(worker runner step 0);
# 抓取失败只记日志,不把排查用的副作用变成新的失败源
try:
html = await page.content()
except Exception:
logger.warning(
"clear_cart:抓取最终页面 HTML 失败(不影响清理结果)",
exc_info=True,
)
finally:
await page.close()
@@ -1058,7 +1072,7 @@ class SiteInteractor:
cart_count = -1
logger.info("clear_cart 完成:removed=%s cart_count=%s", removed, cart_count)
return {"removed_count": removed, "cart_count": cart_count}
return {"removed_count": removed, "cart_count": cart_count, "html": html}
async def remove_item(self, item_id: str) -> dict:
"""删除购物车里指定 item_id 的商品