Files
codex-app-server/cloud/tests/test_chv_muse_p10_checkout.py
T
host 0ebcdfb2a7 fix(chv-muse-r12fix-4): detect_checkout 接进 CDP broker(P10)
R12 真机:detect_checkout 在 chv-guest/、host.py、
executor.py 里零引用,结账页无任何拦截。按 P10 gap §4.1
接线:broker 加载 cloud/chv/checkout_detect.py(同目录
优先,仓库路径兜底;缺失时降级关闭检测、写警告,绝不
crash-loop);snapshot() 每次重算 verdict(aria 行拼伪节点,
与 _form_risk 同形),open() 导航前后两道门——落点是结账
页时返回 form_submit ask 并暂停,上一页是结账页时下一次
导航先审批;ask 批过后同 URL 不再重复 ask(批准即放行,
与 form_risk 同口径);verdict 进 snapshot()/status() 回包。
build.sh:checkout_detect.py 条件拷入 /usr/local/bin/(0644,
P3/P6 同款只警告口径,M4 不硬要求 cloud/),
extra_contents 与两处 lockfile 登记补齐。钱包三腿不在本轮
范围,未动。
2026-11-08 04:31:36 +00:00

175 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""对齐 Muse P10 结账检测测试:detect_checkout 纯函数。
只用标准库,不启动浏览器、不联网。覆盖:
- URL 信号(结账路径 / 购物车 / 普通页 / 坏 URL);
- 无障碍树信号(支付字段 / 密码字段 / 下单按钮 / 金额文本);
- 中英文特征;节点为空;页面金额只作展示信号。
"""
import importlib.util
import os
import sys
import tempfile
import unittest
from pathlib import Path
try:
from cloud.chv.checkout_detect import detect_checkout
except ImportError:
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from cloud.chv.checkout_detect import detect_checkout
def _node(role: str, name: str) -> dict:
return {"role": role, "name": name}
class CheckoutUrlTest(unittest.TestCase):
def test_checkout_path_is_checkout_high(self) -> None:
verdict = detect_checkout("https://shop.example.com/checkout")
self.assertTrue(verdict.is_checkout)
self.assertEqual(verdict.confidence, "medium")
self.assertIn("checkout_url", verdict.reasons)
def test_payment_path_is_checkout(self) -> None:
verdict = detect_checkout(
"https://shop.example.com/order/payment?step=2")
self.assertTrue(verdict.is_checkout)
self.assertIn("checkout_url", verdict.reasons)
def test_cart_path_is_not_checkout(self) -> None:
verdict = detect_checkout("https://shop.example.com/cart")
self.assertFalse(verdict.is_checkout)
self.assertEqual(verdict.confidence, "low")
self.assertIn("cart_url", verdict.reasons)
def test_plain_page_is_not_checkout(self) -> None:
verdict = detect_checkout("https://shop.example.com/products/1")
self.assertFalse(verdict.is_checkout)
self.assertEqual(verdict.confidence, "low")
self.assertEqual(verdict.reasons, [])
def test_bad_url_does_not_crash(self) -> None:
verdict = detect_checkout("::::not a url::::")
self.assertFalse(verdict.is_checkout)
def test_no_nodes_url_only_decision(self) -> None:
verdict = detect_checkout(
"https://shop.example.com/checkout", None)
self.assertTrue(verdict.is_checkout)
class CheckoutNodesTest(unittest.TestCase):
def test_payment_fields_make_checkout_high(self) -> None:
nodes = [_node("textbox", "Card number"),
_node("textbox", "Expiry date"),
_node("textbox", "Security code (CVC)")]
verdict = detect_checkout("https://shop.example.com/buy",
nodes)
self.assertTrue(verdict.is_checkout)
self.assertEqual(verdict.confidence, "high")
self.assertEqual(verdict.form_risk, "payment")
self.assertIn("payment_fields", verdict.reasons)
def test_password_field_marks_form_risk(self) -> None:
nodes = [_node("textbox", "Password")]
verdict = detect_checkout("https://shop.example.com/login",
nodes)
self.assertFalse(verdict.is_checkout)
self.assertEqual(verdict.form_risk, "password")
def test_order_button_plus_amount_is_checkout(self) -> None:
nodes = [_node("button", "Place order"),
_node("text", "Total: $50.00")]
verdict = detect_checkout("https://shop.example.com/review",
nodes)
self.assertTrue(verdict.is_checkout)
self.assertEqual(verdict.confidence, "medium")
self.assertEqual(verdict.amount_text, "$50.00")
def test_order_button_alone_is_not_checkout(self) -> None:
nodes = [_node("button", "Place order")]
verdict = detect_checkout("https://shop.example.com/review",
nodes)
self.assertFalse(verdict.is_checkout)
def test_amount_only_is_not_checkout(self) -> None:
nodes = [_node("text", "Total: $50.00")]
verdict = detect_checkout("https://shop.example.com/review",
nodes)
self.assertFalse(verdict.is_checkout)
self.assertEqual(verdict.amount_text, "$50.00")
def test_chinese_payment_hints(self) -> None:
nodes = [_node("textbox", "卡号"),
_node("button", "立即支付")]
verdict = detect_checkout("https://shop.example.com/buy",
nodes)
self.assertTrue(verdict.is_checkout)
self.assertEqual(verdict.form_risk, "payment")
def test_checkout_url_plus_payment_fields_high(self) -> None:
nodes = [_node("textbox", "Card number"),
_node("button", "Pay now")]
verdict = detect_checkout("https://shop.example.com/checkout",
nodes)
self.assertTrue(verdict.is_checkout)
self.assertEqual(verdict.confidence, "high")
self.assertIn("checkout_url", verdict.reasons)
self.assertIn("payment_fields", verdict.reasons)
def test_yen_and_currency_code_amounts(self) -> None:
nodes = [_node("text", "合計:¥1,200"),
_node("text", "Total 25.00 USD")]
verdict = detect_checkout("https://shop.example.com/review",
nodes)
self.assertEqual(verdict.amount_text, "¥1,200")
def test_empty_nodes_plain_page(self) -> None:
verdict = detect_checkout("https://shop.example.com/", [])
self.assertFalse(verdict.is_checkout)
self.assertIsNone(verdict.form_risk)
self.assertIsNone(verdict.amount_text)
class BuildInfoContentsTest(unittest.TestCase):
"""round-12 修复轮(项 4,P10):checkout_detect 是条件拷入
件——存在时经 extra_contents 登记进 BUILDINFO contents
(不在 BASE_CONTENTS 里,缺失的构建绝不谎称已进镜像,
与 P3 叶子模块同款口径)。"""
def test_extra_contents_include_checkout_detect(self):
root = Path(__file__).resolve().parents[2]
path = root / "chv-guest" / "buildinfo.py"
spec = importlib.util.spec_from_file_location(
"chv_guest_p10_buildinfo", str(path))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
self.assertNotIn("checkout_detect",
module.BASE_CONTENTS)
with tempfile.TemporaryDirectory() as tmp:
out = os.path.join(tmp, "out")
os.makedirs(out)
for name, content in (("disk.raw", b"D"),
("vmlinux", b"K")):
with open(os.path.join(out, name), "wb") as fh:
fh.write(content)
for name, lines in (
("guest-versions-dpkg.txt", ["git 9.9.9-9ubuntu9"]),
("guest-versions-pip.txt", ["playwright==9.9.9"]),
("guest-versions-gt.txt", ["gt version 1.0.0"]),
("guest-versions-chromium.txt",
["chromium_headless_shell-1248"])):
with open(os.path.join(out, name), "w") as fh:
fh.write("\n".join(lines) + "\n")
info = module.build(
out, "chv-guest-24.04-0.164.0-alpha.9-abc1234", "24.04",
"0.164.0-alpha.9", "abc1234", "0" * 64, True, "1248",
["cloud/chv/checkout_detect.py"])
self.assertIn("cloud/chv/checkout_detect.py",
info["contents"])
if __name__ == "__main__":
unittest.main()