feat: 实现受控真实下单安全边界 (#99)
This commit is contained in:
@@ -5,6 +5,7 @@ import unittest
|
||||
from src.pdd_device_service import PddDeviceService
|
||||
from src.pdd_purchase_adapter import PddPurchaseError
|
||||
from src.pdd_u2_purchase_adapter import U2PddPurchaseAdapter
|
||||
from src.pdd_u2_purchase_adapter import U2PddLivePurchaseAdapter
|
||||
|
||||
|
||||
GOODS_URL = "https://mobile.yangkeduo.com/goods.html?goods_id=753136429979"
|
||||
@@ -35,7 +36,8 @@ def panel_xml(quantity: int = 1) -> str:
|
||||
<node content-desc="减少数量" clickable="true" bounds="[390,700][470,780]"/>
|
||||
<node content-desc="增加数量" clickable="true" bounds="[570,700][650,780]"/>
|
||||
<node clickable="true" bounds="[0,2181][1080,2328]">
|
||||
<node text="提交订单 ¥5.03" bounds="[380,2220][700,2290]"/>
|
||||
<node text="提交订单 ¥5.03" enabled="true" visible-to-user="true"
|
||||
bounds="[380,2220][700,2290]"/>
|
||||
</node>
|
||||
</node>
|
||||
</hierarchy>"""
|
||||
@@ -103,6 +105,23 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
||||
select_size_fn=select_size_fn,
|
||||
)
|
||||
|
||||
def _live_adapter(self, device, calls):
|
||||
def select_color_fn(_device, _xml, target, **_kwargs):
|
||||
calls.append(("color", target))
|
||||
return target == "黑色"
|
||||
|
||||
def select_size_fn(_device, _xml, target, **_kwargs):
|
||||
calls.append(("size", target))
|
||||
return target == "3XL【140-165斤】"
|
||||
|
||||
return U2PddLivePurchaseAdapter(
|
||||
"USB-001",
|
||||
device_service=PddDeviceService(connector=lambda _serial: device),
|
||||
sleeper=lambda _seconds: None,
|
||||
select_color_fn=select_color_fn,
|
||||
select_size_fn=select_size_fn,
|
||||
)
|
||||
|
||||
def test_dry_run_reaches_confirmation_without_clicking_submit(self):
|
||||
device = FakeDevice()
|
||||
calls = []
|
||||
@@ -168,6 +187,47 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
||||
self.assertEqual(raised.exception.code, "PURCHASE_GOODS_URL_INVALID")
|
||||
self.assertEqual(device.opened_urls, [])
|
||||
|
||||
def test_live_adapter_clicks_unique_submit_target_only_once(self):
|
||||
device = FakeDevice()
|
||||
adapter = self._live_adapter(device, [])
|
||||
adapter.open_goods(GOODS_URL)
|
||||
adapter.select_options(
|
||||
{"color": "黑色", "size": "3XL【140-165斤】"}
|
||||
)
|
||||
adapter.set_quantity(2)
|
||||
|
||||
state = adapter.read_state()
|
||||
adapter.submit_order_once()
|
||||
with self.assertRaises(PddPurchaseError) as raised:
|
||||
adapter.submit_order_once()
|
||||
|
||||
self.assertEqual(state.submit_candidate_count, 1)
|
||||
self.assertEqual(raised.exception.code, "PURCHASE_SUBMIT_ALREADY_ATTEMPTED")
|
||||
# 第一次点击采购入口,第二次且仅一次点击最终提交。
|
||||
self.assertEqual(len(device.clicks), 2)
|
||||
adapter.close()
|
||||
|
||||
def test_live_adapter_rejects_multiple_submit_targets_without_click(self):
|
||||
device = FakeDevice()
|
||||
adapter = self._live_adapter(device, [])
|
||||
adapter.open_goods(GOODS_URL)
|
||||
adapter.select_options(
|
||||
{"color": "黑色", "size": "3XL【140-165斤】"}
|
||||
)
|
||||
device.special_xml = panel_xml().replace(
|
||||
"</hierarchy>",
|
||||
'<node text="确认购买" enabled="true" visible-to-user="true" '
|
||||
'bounds="[50,2200][300,2300]"/></hierarchy>',
|
||||
)
|
||||
device.mode = "special"
|
||||
|
||||
with self.assertRaises(PddPurchaseError) as raised:
|
||||
adapter.submit_order_once()
|
||||
|
||||
self.assertEqual(raised.exception.code, "PURCHASE_SUBMIT_TARGET_AMBIGUOUS")
|
||||
self.assertEqual(len(device.clicks), 1)
|
||||
adapter.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user