fix: 稳定采购地址页面切换 (#221)
This commit is contained in:
@@ -69,6 +69,7 @@ _RISK_MARKERS = ("操作频繁", "异常请求", "风险提示", "账号异常")
|
|||||||
_PAYMENT_MARKERS = ("输入支付密码", "立即支付", "支付成功", "支付失败")
|
_PAYMENT_MARKERS = ("输入支付密码", "立即支付", "支付成功", "支付失败")
|
||||||
_FINAL_SUBMIT_MARKERS = ("提交订单", "现在买,仅", "确认购买")
|
_FINAL_SUBMIT_MARKERS = ("提交订单", "现在买,仅", "确认购买")
|
||||||
_OUT_OF_STOCK_MARKERS = ("已售罄", "暂时缺货", "库存不足", "该商品已售罄")
|
_OUT_OF_STOCK_MARKERS = ("已售罄", "暂时缺货", "库存不足", "该商品已售罄")
|
||||||
|
_ADDRESS_ACTION_SETTLE_SECONDS = 1.0
|
||||||
_SUPPORTED_OPTION_KEYS = frozenset({"color", "size"})
|
_SUPPORTED_OPTION_KEYS = frozenset({"color", "size"})
|
||||||
_MAX_QUANTITY_BUTTON_CLICKS = 5
|
_MAX_QUANTITY_BUTTON_CLICKS = 5
|
||||||
_KEYBOARD_STATUS_MARKERS = (
|
_KEYBOARD_STATUS_MARKERS = (
|
||||||
@@ -1378,6 +1379,7 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
"PURCHASE_ADDRESS_ENTRY_AMBIGUOUS",
|
"PURCHASE_ADDRESS_ENTRY_AMBIGUOUS",
|
||||||
"规格面板没有唯一可靠的收货地址入口",
|
"规格面板没有唯一可靠的收货地址入口",
|
||||||
)
|
)
|
||||||
|
self._settle_after_address_action()
|
||||||
|
|
||||||
panel_root = self._wait_for_address_page("panel")
|
panel_root = self._wait_for_address_page("panel")
|
||||||
edit_root = self._open_address_edit_page(panel_root)
|
edit_root = self._open_address_edit_page(panel_root)
|
||||||
@@ -1410,12 +1412,14 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
step="purchase_update_shipping_address",
|
step="purchase_update_shipping_address",
|
||||||
)
|
)
|
||||||
editor.set_text(new_address)
|
editor.set_text(new_address)
|
||||||
|
self._settle_after_address_action()
|
||||||
save_target = self._wait_for_stable_address_save(new_address)
|
save_target = self._wait_for_stable_address_save(new_address)
|
||||||
self._click_unique_address_target(
|
self._click_unique_address_target(
|
||||||
[save_target],
|
[save_target],
|
||||||
"PURCHASE_ADDRESS_SAVE_AMBIGUOUS",
|
"PURCHASE_ADDRESS_SAVE_AMBIGUOUS",
|
||||||
"修改页没有唯一可靠的保存按钮",
|
"修改页没有唯一可靠的保存按钮",
|
||||||
)
|
)
|
||||||
|
self._settle_after_address_action()
|
||||||
|
|
||||||
saved_root, saved_page = self._wait_after_address_save(new_address)
|
saved_root, saved_page = self._wait_after_address_save(new_address)
|
||||||
if saved_page == "confirmation":
|
if saved_page == "confirmation":
|
||||||
@@ -1426,6 +1430,7 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
"PURCHASE_ADDRESS_BACK_AMBIGUOUS",
|
"PURCHASE_ADDRESS_BACK_AMBIGUOUS",
|
||||||
"收货地址页没有唯一可靠的返回按钮",
|
"收货地址页没有唯一可靠的返回按钮",
|
||||||
)
|
)
|
||||||
|
self._settle_after_address_action()
|
||||||
self._wait_for_address_page("confirmation")
|
self._wait_for_address_page("confirmation")
|
||||||
except PddPurchaseError:
|
except PddPurchaseError:
|
||||||
raise
|
raise
|
||||||
@@ -1451,6 +1456,11 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
(left + right) // 2, (top + bottom) // 2
|
(left + right) // 2, (top + bottom) // 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _settle_after_address_action(self) -> None:
|
||||||
|
"""关键地址操作后留出固定时间,再继续按页面状态确认。"""
|
||||||
|
|
||||||
|
self._sleep(_ADDRESS_ACTION_SETTLE_SECONDS)
|
||||||
|
|
||||||
def _open_address_edit_page(self, panel_root: ET.Element) -> ET.Element:
|
def _open_address_edit_page(self, panel_root: ET.Element) -> ET.Element:
|
||||||
"""稳定识别“修改”按钮;首次点击丢失时最多安全重试一次。"""
|
"""稳定识别“修改”按钮;首次点击丢失时最多安全重试一次。"""
|
||||||
|
|
||||||
@@ -1501,6 +1511,9 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
"PURCHASE_ADDRESS_EDIT_AMBIGUOUS",
|
"PURCHASE_ADDRESS_EDIT_AMBIGUOUS",
|
||||||
"收货地址页没有唯一可靠的修改按钮",
|
"收货地址页没有唯一可靠的修改按钮",
|
||||||
)
|
)
|
||||||
|
self._settle_after_address_action()
|
||||||
|
# 固定稳定等待不能占用原页面切换超时预算。
|
||||||
|
deadline += _ADDRESS_ACTION_SETTLE_SECONDS
|
||||||
click_attempts += 1
|
click_attempts += 1
|
||||||
if first_clicked_target is None:
|
if first_clicked_target is None:
|
||||||
first_clicked_target = current_target
|
first_clicked_target = current_target
|
||||||
@@ -1693,6 +1706,9 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter):
|
|||||||
if overlay_stable_reads >= 3 and system_back_attempts == 0:
|
if overlay_stable_reads >= 3 and system_back_attempts == 0:
|
||||||
# 只关闭已知系统浮层;保存按钮和 PDD 页面都不重试点击。
|
# 只关闭已知系统浮层;保存按钮和 PDD 页面都不重试点击。
|
||||||
self._require_device().press("back")
|
self._require_device().press("back")
|
||||||
|
self._settle_after_address_action()
|
||||||
|
# 固定稳定等待不能占用原浮层关闭确认超时预算。
|
||||||
|
deadline += _ADDRESS_ACTION_SETTLE_SECONDS
|
||||||
system_back_attempts = 1
|
system_back_attempts = 1
|
||||||
overlay_stable_reads = 0
|
overlay_stable_reads = 0
|
||||||
self._sleep(0.2)
|
self._sleep(0.2)
|
||||||
|
|||||||
@@ -24,11 +24,13 @@ FIXTURES = Path(__file__).parent / "fixtures"
|
|||||||
class FakeClock:
|
class FakeClock:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.now = 0.0
|
self.now = 0.0
|
||||||
|
self.sleeps = []
|
||||||
|
|
||||||
def monotonic(self) -> float:
|
def monotonic(self) -> float:
|
||||||
return self.now
|
return self.now
|
||||||
|
|
||||||
def sleep(self, seconds: float) -> None:
|
def sleep(self, seconds: float) -> None:
|
||||||
|
self.sleeps.append(seconds)
|
||||||
self.now += seconds
|
self.now += seconds
|
||||||
|
|
||||||
|
|
||||||
@@ -952,8 +954,14 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_live_adapter_updates_address_and_returns_to_confirmation(self):
|
def test_live_adapter_updates_address_and_returns_to_confirmation(self):
|
||||||
|
clock = FakeClock()
|
||||||
device = AddressFlowDevice()
|
device = AddressFlowDevice()
|
||||||
adapter = self._live_adapter(device, [])
|
adapter = self._live_adapter(
|
||||||
|
device,
|
||||||
|
[],
|
||||||
|
sleeper=clock.sleep,
|
||||||
|
monotonic=clock.monotonic,
|
||||||
|
)
|
||||||
adapter.open_goods(GOODS_URL)
|
adapter.open_goods(GOODS_URL)
|
||||||
adapter.select_options(
|
adapter.select_options(
|
||||||
{"color": "黑色", "size": "3XL【140-165斤】"}
|
{"color": "黑色", "size": "3XL【140-165斤】"}
|
||||||
@@ -970,6 +978,7 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
|||||||
self.assertEqual(state.page_kind, "order_confirmation")
|
self.assertEqual(state.page_kind, "order_confirmation")
|
||||||
self.assertEqual(state.quantity, 1)
|
self.assertEqual(state.quantity, 1)
|
||||||
self.assertEqual(state.price_cent, 503)
|
self.assertEqual(state.price_cent, 503)
|
||||||
|
self.assertEqual(clock.sleeps.count(1.0), 5)
|
||||||
adapter.close()
|
adapter.close()
|
||||||
|
|
||||||
def test_multiple_addresses_modify_only_default_card(self):
|
def test_multiple_addresses_modify_only_default_card(self):
|
||||||
@@ -1243,8 +1252,14 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
|||||||
adapter.close()
|
adapter.close()
|
||||||
|
|
||||||
def test_persistent_coloros_overlay_is_dismissed_with_one_system_back(self):
|
def test_persistent_coloros_overlay_is_dismissed_with_one_system_back(self):
|
||||||
|
clock = FakeClock()
|
||||||
device = AddressSaveOverlayDevice()
|
device = AddressSaveOverlayDevice()
|
||||||
adapter = self._live_adapter(device, [])
|
adapter = self._live_adapter(
|
||||||
|
device,
|
||||||
|
[],
|
||||||
|
sleeper=clock.sleep,
|
||||||
|
monotonic=clock.monotonic,
|
||||||
|
)
|
||||||
adapter.open_goods(GOODS_URL)
|
adapter.open_goods(GOODS_URL)
|
||||||
adapter.select_options(
|
adapter.select_options(
|
||||||
{"color": "黑色", "size": "3XL【140-165斤】"}
|
{"color": "黑色", "size": "3XL【140-165斤】"}
|
||||||
@@ -1255,6 +1270,7 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
|||||||
self.assertEqual(device.save_clicks, 1)
|
self.assertEqual(device.save_clicks, 1)
|
||||||
self.assertEqual(device.presses, ["back"])
|
self.assertEqual(device.presses, ["back"])
|
||||||
self.assertEqual(device.mode, "panel")
|
self.assertEqual(device.mode, "panel")
|
||||||
|
self.assertEqual(clock.sleeps.count(1.0), 6)
|
||||||
adapter.close()
|
adapter.close()
|
||||||
|
|
||||||
def test_coloros_overlay_is_never_dismissed_more_than_once(self):
|
def test_coloros_overlay_is_never_dismissed_more_than_once(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user