From 63bd873c260f770ab78e39937f815082f00be422 Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Wed, 5 Aug 2026 17:39:12 +0800 Subject: [PATCH] fix(client): accept evidenced rolled target color --- .../src/cmbuyer_client/pdd/sku_selection.py | 14 +++++++++++ client/tests/pdd/test_sku_selection.py | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/client/src/cmbuyer_client/pdd/sku_selection.py b/client/src/cmbuyer_client/pdd/sku_selection.py index 2538aa7..cb60f1a 100644 --- a/client/src/cmbuyer_client/pdd/sku_selection.py +++ b/client/src/cmbuyer_client/pdd/sku_selection.py @@ -19,6 +19,7 @@ EXPECTED_UNIT_PRICE = "12.88" TASK_TO_UI_SELECTION = {("黑色CHA(纯棉)", "M(建议100-115)"): ("黑色 CHA (纯棉)", "M(建议100-115)")} _TARGET_COLOR_UI, _TARGET_SIZE_UI = next(iter(TASK_TO_UI_SELECTION.values())) _TARGET_COLOR_UNROLLED_BOUNDS = "[372,1188][684,1587]" +_TARGET_COLOR_ROLLED_ALT_BOUNDS = "[126,1000][438,1024]" _TARGET_SIZE_BOUNDS = "[439,1582][831,1667]" _ENTRY = "快要抢光 ¥ 12.88" _ENTRY_PROMOTION_LABEL = "快要抢光" @@ -235,6 +236,19 @@ _PANEL_SPECS = ( "[36,1000][1080,1483]", "[372,1000][684,1024]", True, "[36,1506][114,1552]", _TARGET_SIZE_UI, ), + # T-104 真机证据证明:人工重新打开已选面板时,颜色横向列表可把同一目标卡片精确滚到 + # 左侧;只增加该证据坐标的完整 profile,不放宽文字、selected、价格或其余结构。 + _PanelSpec( + _PanelProfile.TARGETS_SELECTED, + "[0,366][1080,1000]", "[0,1000][1080,2079]", + _DualPriceLayout( + "[396,498][895,570]", _ROLLED_CURRENT_PRICE, "[396,503][712,570]", + _ROLLED_ORIGINAL_PRICE, "[730,503][895,570]", + ), + _TARGET_SUMMARY, "[396,654][1053,716]", None, + "[36,1000][1080,1483]", _TARGET_COLOR_ROLLED_ALT_BOUNDS, True, + "[36,1506][114,1552]", _TARGET_SIZE_UI, + ), ) diff --git a/client/tests/pdd/test_sku_selection.py b/client/tests/pdd/test_sku_selection.py index ad5faba..9c738f8 100644 --- a/client/tests/pdd/test_sku_selection.py +++ b/client/tests/pdd/test_sku_selection.py @@ -1730,6 +1730,30 @@ class SkuExitSpikeCapturerTests(unittest.TestCase): self.assertEqual(_actions(device, "click"), []) self.assertEqual(_actions(device, "swipe"), []) + def test_evidence_bound_rolled_target_color_variant_is_exactly_accepted(self) -> None: + hierarchy = _M_FIXTURE.read_text(encoding="utf-8") + old_bounds = "[372,1000][684,1024]" + new_bounds = "[126,1000][438,1024]" + self.assertEqual(hierarchy.count(old_bounds), 4) + device = _ExitEvidenceDevice(hierarchy.replace(old_bounds, new_bounds)) + + with TemporaryDirectory() as temporary: + target = Path(temporary) / "exit-evidence" + result = self._capturer(_FakeAdb(), device).capture("device-1", target) + manifest = json.loads(result.manifest_path.read_text(encoding="utf-8")) + + self.assertEqual(manifest["back_attempts"], 1) + self.assertEqual(manifest["post_exit_status"], "human_review_required") + self.assertEqual(len(_actions(device, "pressKey")), 1) + + unknown_device = _ExitEvidenceDevice(hierarchy.replace(old_bounds, "[127,1000][439,1024]")) + with TemporaryDirectory() as temporary: + target = Path(temporary) / "unknown" + with self.assertRaises(SkuSelectionError): + self._capturer(_FakeAdb(), unknown_device).capture("device-1", target) + self.assertEqual(_actions(unknown_device, "pressKey"), []) + self.assertFalse(target.exists()) + def test_precondition_mismatch_or_drift_never_sends_back_or_leaves_artifacts(self) -> None: class WrongScreen(_ExitEvidenceDevice): def window_size(self) -> tuple[int, int]: