feat(client): productionize proven sku reveal flow
This commit is contained in:
@@ -18,17 +18,19 @@ import cmbuyer_client.pdd.sku_reveal_spike as reveal_module
|
||||
from cmbuyer_client.device.adb import AdbDevice, DeviceInspection
|
||||
from cmbuyer_client.pdd.sku_reveal_spike import (
|
||||
_annotate_reveal_failure,
|
||||
_candidate_projection,
|
||||
_RevealEvidenceAdapter,
|
||||
safe_reveal_failure_stage,
|
||||
SkuRevealSpikeCapturer,
|
||||
SkuRevealSpikeError,
|
||||
_require_safe_reveal_path,
|
||||
)
|
||||
from cmbuyer_client.pdd.sku_selection import (
|
||||
SkuSelectionError,
|
||||
_annotate_sku_entry_failure,
|
||||
_parse_nodes,
|
||||
_require_safe_reveal_path,
|
||||
_revealed_unselected_projection as _candidate_projection,
|
||||
)
|
||||
from cmbuyer_client.pdd.sku_selection_runner import (
|
||||
UiautomatorSkuPanelAdapter as _RevealEvidenceAdapter,
|
||||
)
|
||||
|
||||
|
||||
@@ -350,7 +352,7 @@ def _candidate_cross_variant_residue(variant: str, kind: str) -> str:
|
||||
|
||||
|
||||
def _candidate_with_color_unselected() -> str:
|
||||
root = ElementTree.fromstring(_candidate_unselected())
|
||||
root = ElementTree.fromstring(_candidate_current_only())
|
||||
target = next(
|
||||
node
|
||||
for node in root.iter("node")
|
||||
@@ -364,7 +366,7 @@ def _candidate_with_color_unselected() -> str:
|
||||
|
||||
|
||||
def _candidate_with_submit_risk(kind: str) -> str:
|
||||
root = ElementTree.fromstring(_candidate_unselected())
|
||||
root = ElementTree.fromstring(_candidate_current_only())
|
||||
parents = {child: parent for parent in root.iter() for child in parent}
|
||||
submit = next(
|
||||
node
|
||||
@@ -379,6 +381,13 @@ def _candidate_with_submit_risk(kind: str) -> str:
|
||||
parent.append(ElementTree.fromstring(ElementTree.tostring(submit, encoding="unicode")))
|
||||
elif kind == "moved_up":
|
||||
submit.set("bounds", "[285,1900][795,1959]")
|
||||
elif kind in {"extra_altered", "extra_moved_up"}:
|
||||
extra = ElementTree.fromstring(ElementTree.tostring(submit, encoding="unicode"))
|
||||
if kind == "extra_altered":
|
||||
extra.set("text", "异常提交订单文案")
|
||||
else:
|
||||
extra.set("bounds", "[285,1900][795,1959]")
|
||||
parent.append(extra)
|
||||
else:
|
||||
raise AssertionError(kind)
|
||||
return ElementTree.tostring(root, encoding="unicode")
|
||||
@@ -416,9 +425,9 @@ def _png() -> str:
|
||||
class _FakeDevice:
|
||||
def __init__(self) -> None:
|
||||
self.hierarchy = "<hierarchy />"
|
||||
self.empty_hierarchy = _EMPTY
|
||||
self.color_hierarchy = _COLOR_ONLY
|
||||
self.after_hierarchy = _candidate_unselected()
|
||||
self.empty_hierarchy = _CURRENT_ONLY_EMPTY
|
||||
self.color_hierarchy = _CURRENT_ONLY_COLOR
|
||||
self.after_hierarchy = _candidate_current_only()
|
||||
self.calls: list[tuple[object, ...]] = []
|
||||
self.swipe_error = False
|
||||
|
||||
@@ -545,8 +554,9 @@ class SkuRevealSpikeTests(unittest.TestCase):
|
||||
self.assertTrue((target / "after" / "hierarchy.xml").is_file())
|
||||
|
||||
def test_candidate_price_variants_reject_hybrid_duplicate_unknown_and_parent_drift(self) -> None:
|
||||
# 两个真实嵌套 variant 各自唯一命中;任意混搭、额外子节点或父子关系漂移均拒绝。
|
||||
_candidate_projection(_parse_nodes(_candidate_unselected()))
|
||||
# 生产只放行 current-only;历史 dual 及任意混搭、额外节点、父链漂移均拒绝。
|
||||
with self.assertRaises(SkuSelectionError):
|
||||
_candidate_projection(_parse_nodes(_candidate_unselected()))
|
||||
_candidate_projection(_parse_nodes(_candidate_current_only()))
|
||||
for variant in ("dual", "current_only"):
|
||||
kinds = ["hybrid", "duplicate", "unknown", "unknown_child", "parent_drift"]
|
||||
@@ -683,7 +693,7 @@ class SkuRevealSpikeTests(unittest.TestCase):
|
||||
self._assert_after_rejected_once(_candidate_with_color_unselected())
|
||||
|
||||
def test_submit_hard_reject_zone_risk_is_not_published_or_retried(self) -> None:
|
||||
for kind in ("missing", "duplicate", "moved_up"):
|
||||
for kind in ("missing", "duplicate", "moved_up", "extra_altered", "extra_moved_up"):
|
||||
with self.subTest(kind=kind):
|
||||
self._assert_after_rejected_once(_candidate_with_submit_risk(kind))
|
||||
|
||||
@@ -739,7 +749,7 @@ class SkuRevealSpikeTests(unittest.TestCase):
|
||||
device.jsonrpc_call = drift # type: ignore[method-assign]
|
||||
with TemporaryDirectory() as directory:
|
||||
target = Path(directory) / "evidence"
|
||||
with self.assertRaises(SkuRevealSpikeError) as raised:
|
||||
with self.assertRaises((SkuRevealSpikeError, SkuSelectionError)) as raised:
|
||||
self._capturer(device).capture(
|
||||
"192.168.0.173:5555",
|
||||
"937122477375",
|
||||
@@ -850,7 +860,7 @@ class SkuRevealSpikeTests(unittest.TestCase):
|
||||
"not-a-bound",
|
||||
),
|
||||
):
|
||||
with self.subTest(), self.assertRaises(SkuRevealSpikeError):
|
||||
with self.subTest(), self.assertRaises((SkuRevealSpikeError, SkuSelectionError)):
|
||||
_require_safe_reveal_path(_parse_nodes(hierarchy))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user