fix: 修正规格返回后的繁简体复核 (#260)
This commit is contained in:
@@ -597,9 +597,11 @@ def _page_kind(root: ET.Element, current_package: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _selected(root: ET.Element, target: str) -> bool:
|
def _selected(root: ET.Element, target: str) -> bool:
|
||||||
"""从最新控件树确认一个规格已选中。"""
|
"""按采购规格的繁简归一化语义确认目标仍明确处于选中状态。"""
|
||||||
|
|
||||||
checked_target = target.strip().casefold()
|
checked_target = normalize_spec_text(target)
|
||||||
|
if not checked_target:
|
||||||
|
return False
|
||||||
parents = {
|
parents = {
|
||||||
child: parent
|
child: parent
|
||||||
for parent in root.iter()
|
for parent in root.iter()
|
||||||
@@ -608,8 +610,8 @@ def _selected(root: ET.Element, target: str) -> bool:
|
|||||||
}
|
}
|
||||||
for node in root.iter("node"):
|
for node in root.iter("node"):
|
||||||
labels = {
|
labels = {
|
||||||
node.get("text", "").strip().casefold(),
|
normalize_spec_text(node.get("text", "")),
|
||||||
node.get("content-desc", "").strip().casefold(),
|
normalize_spec_text(node.get("content-desc", "")),
|
||||||
}
|
}
|
||||||
if checked_target not in labels:
|
if checked_target not in labels:
|
||||||
continue
|
continue
|
||||||
@@ -624,7 +626,8 @@ def _selected(root: ET.Element, target: str) -> bool:
|
|||||||
|
|
||||||
# 选中节点滑出屏幕后,PDD 仍会在顶部“已选”摘要中保留完整文字。
|
# 选中节点滑出屏幕后,PDD 仍会在顶部“已选”摘要中保留完整文字。
|
||||||
return any(
|
return any(
|
||||||
label.startswith("已选") and target.strip() in label
|
label.startswith(("已选", "已選", "已选择", "已選擇"))
|
||||||
|
and checked_target in normalize_spec_text(label)
|
||||||
for label in _labels(root)
|
for label in _labels(root)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1285,13 +1288,24 @@ class U2PddPurchaseAdapter(PddPurchaseAdapter):
|
|||||||
|
|
||||||
current_xml = self._dump_hierarchy()
|
current_xml = self._dump_hierarchy()
|
||||||
root = _parse_xml(current_xml)
|
root = _parse_xml(current_xml)
|
||||||
if _page_kind(root, "") != "order_confirmation" or not _selected(
|
current_page_kind = _page_kind(root, "")
|
||||||
root, expected_snapshot.selected_color
|
if current_page_kind != "order_confirmation":
|
||||||
):
|
|
||||||
raise PddPurchaseError(
|
raise PddPurchaseError(
|
||||||
"PURCHASE_SPEC_CONTEXT_CHANGED",
|
"PURCHASE_SPEC_CONTEXT_CHANGED",
|
||||||
"等待规格解析期间页面或已选颜色发生变化",
|
"等待规格解析期间页面已离开规格确认页",
|
||||||
step="purchase_resolve_options",
|
step="purchase_resolve_options",
|
||||||
|
diagnostics={
|
||||||
|
"context_check": "page_kind",
|
||||||
|
"expected_page_kind": "order_confirmation",
|
||||||
|
"observed_page_kind": current_page_kind,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if not _selected(root, expected_snapshot.selected_color):
|
||||||
|
raise PddPurchaseError(
|
||||||
|
"PURCHASE_SPEC_CONTEXT_CHANGED",
|
||||||
|
"等待规格解析期间已选颜色发生变化",
|
||||||
|
step="purchase_resolve_options",
|
||||||
|
diagnostics={"context_check": "selected_color"},
|
||||||
)
|
)
|
||||||
|
|
||||||
current_xml = self._restore_purchase_panel_color_region(current_xml)
|
current_xml = self._restore_purchase_panel_color_region(current_xml)
|
||||||
|
|||||||
@@ -1031,6 +1031,102 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
adapter.close()
|
adapter.close()
|
||||||
|
|
||||||
|
def test_apply_resolved_size_accepts_selected_simplified_color_for_traditional_target(self):
|
||||||
|
device = FakeDevice()
|
||||||
|
selected = []
|
||||||
|
traditional_color = "縹緲仙姬綰【黑色】"
|
||||||
|
simplified_color = "缥缈仙姬绾【黑色】"
|
||||||
|
resolved_size = "均码【80-120斤】"
|
||||||
|
snapshot = PurchaseSpecCandidateSnapshot.build(
|
||||||
|
goods_id="753136429979",
|
||||||
|
selected_color=traditional_color,
|
||||||
|
target_size="均碼【40.0-60.0公斤】",
|
||||||
|
dimension_name="尺码",
|
||||||
|
observations=(PurchaseSizeObservation(resolved_size, True),),
|
||||||
|
observed_at="2026-08-18T01:01:36Z",
|
||||||
|
)
|
||||||
|
adapter = U2PddPurchaseAdapter(
|
||||||
|
"USB-001",
|
||||||
|
device_service=PddDeviceService(connector=lambda _serial: device),
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
select_size_fn=lambda _device, _xml, target, **_kwargs: (
|
||||||
|
selected.append(target) or True
|
||||||
|
),
|
||||||
|
size_candidate_collector=lambda _device: SpecDimension(
|
||||||
|
"size", "尺码", (DimensionValue(resolved_size, True),)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
adapter.open_goods(GOODS_URL)
|
||||||
|
device.mode = "special"
|
||||||
|
device.special_xml = panel_xml().replace(
|
||||||
|
"黑色", simplified_color
|
||||||
|
).replace("3XL【140-165斤】", resolved_size)
|
||||||
|
|
||||||
|
adapter.apply_resolved_size(snapshot, snapshot.candidates[0])
|
||||||
|
|
||||||
|
self.assertEqual(selected, [resolved_size])
|
||||||
|
adapter._requested_options = {
|
||||||
|
"color": traditional_color,
|
||||||
|
"size": resolved_size,
|
||||||
|
}
|
||||||
|
self.assertEqual(
|
||||||
|
adapter.read_state().selected_options,
|
||||||
|
{"color": traditional_color, "size": resolved_size},
|
||||||
|
)
|
||||||
|
adapter.close()
|
||||||
|
|
||||||
|
def test_apply_resolved_size_distinguishes_page_and_color_context_changes(self):
|
||||||
|
resolved_size = "均码【80-120斤】"
|
||||||
|
snapshot = PurchaseSpecCandidateSnapshot.build(
|
||||||
|
goods_id="753136429979",
|
||||||
|
selected_color="縹緲仙姬綰【黑色】",
|
||||||
|
target_size="均碼【40.0-60.0公斤】",
|
||||||
|
dimension_name="尺码",
|
||||||
|
observations=(PurchaseSizeObservation(resolved_size, True),),
|
||||||
|
observed_at="2026-08-18T01:01:36Z",
|
||||||
|
)
|
||||||
|
|
||||||
|
cases = (
|
||||||
|
("page_kind", home_xml(), "页面已离开规格确认页"),
|
||||||
|
(
|
||||||
|
"selected_color",
|
||||||
|
panel_xml().replace("selected=\"true\"", "selected=\"false\"")
|
||||||
|
.replace("已选: 黑色", "已选: 白色")
|
||||||
|
.replace("黑色", "缥缈仙姬绾【白色】")
|
||||||
|
.replace("3XL【140-165斤】", resolved_size),
|
||||||
|
"已选颜色发生变化",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
for context_check, current_xml, expected_message in cases:
|
||||||
|
with self.subTest(context_check=context_check):
|
||||||
|
device = FakeDevice()
|
||||||
|
adapter = U2PddPurchaseAdapter(
|
||||||
|
"USB-001",
|
||||||
|
device_service=PddDeviceService(
|
||||||
|
connector=lambda _serial, current=device: current
|
||||||
|
),
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
select_size_fn=lambda *_args, **_kwargs: True,
|
||||||
|
size_candidate_collector=lambda _device: SpecDimension(
|
||||||
|
"size", "尺码", (DimensionValue(resolved_size, True),)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
adapter.open_goods(GOODS_URL)
|
||||||
|
device.mode = "special"
|
||||||
|
device.special_xml = current_xml
|
||||||
|
|
||||||
|
with self.assertRaises(PddPurchaseError) as raised:
|
||||||
|
adapter.apply_resolved_size(snapshot, snapshot.candidates[0])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
raised.exception.code, "PURCHASE_SPEC_CONTEXT_CHANGED"
|
||||||
|
)
|
||||||
|
self.assertIn(expected_message, raised.exception.message)
|
||||||
|
self.assertEqual(
|
||||||
|
raised.exception.diagnostics["context_check"], context_check
|
||||||
|
)
|
||||||
|
adapter.close()
|
||||||
|
|
||||||
def test_apply_resolved_size_stops_when_candidate_snapshot_changed(self):
|
def test_apply_resolved_size_stops_when_candidate_snapshot_changed(self):
|
||||||
device = FakeDevice()
|
device = FakeDevice()
|
||||||
selections = []
|
selections = []
|
||||||
|
|||||||
Reference in New Issue
Block a user