fix: 安全兼容采购规格繁简匹配 (#251)

This commit is contained in:
chengma
2026-08-17 15:20:35 +08:00
parent 1927e3edb6
commit 134514e382
4 changed files with 373 additions and 56 deletions
@@ -1618,6 +1618,35 @@ class U2PddPurchaseAdapterTest(unittest.TestCase):
self.assertIn("purchase_select_size", operations)
adapter.close()
def test_failed_option_stage_is_recorded_as_failed(self):
cases = (
({"color": "不存在的颜色"}, "purchase_select_color"),
(
{"color": "黑色", "size": "不存在的尺码"},
"purchase_select_size",
),
)
for options, expected_operation in cases:
with self.subTest(operation=expected_operation):
device = FakeDevice()
adapter = self._adapter(device, [])
records = []
trace = TaskPerformanceTrace(sink=records.append)
trace.bind_task(f"PUR-{expected_operation}")
adapter.open_goods(GOODS_URL)
with trace.activate(), self.assertRaises(PddPurchaseError):
adapter.select_options(options)
matching = [
record
for record in records
if record["operation"] == expected_operation
]
self.assertEqual(len(matching), 1)
self.assertEqual(matching[0]["result"], "failed")
adapter.close()
def test_same_quantity_does_not_focus_editor(self):
device = FakeDevice()
adapter = self._adapter(device, [])
+89 -3
View File
@@ -6,7 +6,10 @@ import xml.etree.ElementTree as ET
from src.util.select_color_size import (
color_selection_failure_reason,
normalize_spec_text,
select_color,
select_size,
size_selection_failure_reason,
)
@@ -16,9 +19,15 @@ FIXTURES = Path(__file__).parent / "fixtures"
class StaticColorDevice:
"""模拟没有滚动属性的图片颜色规格面板。"""
def __init__(self, xml_data: str, confirm_selection: bool = True) -> None:
def __init__(
self,
xml_data: str,
confirm_selection: bool = True,
selected_text: str = "测试黑色",
) -> None:
self.xml_data = xml_data
self.confirm_selection = confirm_selection
self.selected_text = selected_text
self.clicks = []
self.swipes = []
@@ -31,10 +40,10 @@ class StaticColorDevice:
return
root = ET.fromstring(self.xml_data)
for node in root.iter("node"):
if node.get("text", "").strip() == "测试黑色":
if node.get("text", "").strip() == self.selected_text:
node.set("selected", "true")
if node.get("text", "").strip().startswith("请选择"):
node.set("text", "已选: 测试黑色")
node.set("text", f"已选: {self.selected_text}")
self.xml_data = ET.tostring(root, encoding="unicode")
def swipe(self, *args, **kwargs) -> None:
@@ -122,6 +131,83 @@ class StaticColorSelectionTest(unittest.TestCase):
self.assertEqual(device.clicks, [])
self.assertEqual(device.swipes, [])
def test_traditional_color_matches_unique_simplified_card(self):
simplified = "缥缈仙姬绾【黑色】"
traditional = "縹緲仙姬綰【黑色】"
panel_xml = self.panel_xml.replace("测试黑色", simplified)
device = StaticColorDevice(panel_xml, selected_text=simplified)
selected = select_color(
device,
panel_xml,
traditional,
action_delay=0.001,
)
self.assertEqual(normalize_spec_text(traditional), simplified.casefold())
self.assertTrue(selected)
self.assertEqual(device.clicks, [(194, 1389)])
def test_traditional_size_matches_unique_simplified_option(self):
simplified = "均码【40.0-60.0公斤】"
traditional = "均碼【40.0-60.0公斤】"
panel_xml = self.panel_xml.replace('text="M"', f'text="{simplified}"')
device = StaticColorDevice(panel_xml, selected_text=simplified)
selected = select_size(
device,
panel_xml,
traditional,
action_delay=0.001,
)
self.assertTrue(selected)
self.assertEqual(device.clicks, [(77, 1762)])
def test_normalized_duplicate_color_candidates_are_not_clicked(self):
simplified = "缥缈仙姬绾【黑色】"
traditional = "縹緲仙姬綰【黑色】"
panel_xml = self.panel_xml.replace("测试黑色", simplified).replace(
"测试红色", simplified
)
device = StaticColorDevice(panel_xml, selected_text=simplified)
selected = select_color(
device,
panel_xml,
traditional,
action_delay=0.001,
)
self.assertFalse(selected)
self.assertEqual(device.clicks, [])
self.assertEqual(
color_selection_failure_reason(panel_xml, traditional),
"target_ambiguous",
)
def test_normalized_duplicate_size_candidates_are_not_clicked(self):
simplified = "均码【40.0-60.0公斤】"
traditional = "均碼【40.0-60.0公斤】"
panel_xml = self.panel_xml.replace('text="M"', f'text="{simplified}"').replace(
'text="L"', f'text="{simplified}"'
)
device = StaticColorDevice(panel_xml, selected_text=simplified)
selected = select_size(
device,
panel_xml,
traditional,
action_delay=0.001,
)
self.assertFalse(selected)
self.assertEqual(device.clicks, [])
self.assertEqual(
size_selection_failure_reason(panel_xml, traditional),
"target_ambiguous",
)
if __name__ == "__main__":
unittest.main()