fix: 完整遍历尺码与套餐第二规格 (#167)

This commit is contained in:
chengma
2026-08-11 17:20:37 +08:00
parent 22bf3fe82c
commit 18678e1b82
2 changed files with 307 additions and 2 deletions
+87
View File
@@ -460,6 +460,55 @@ class DefaultPackageDevice(DefaultSizeDevice):
return super()._spec_xml().replace('text="尺码"', 'text="套餐"')
class HorizontalPackageDevice:
"""模拟独立横向套餐列表,每屏只有三个且相邻页面有重叠。"""
packages = tuple(f"套餐{i}" for i in range(1, 8))
def __init__(self, expected_count=7):
self.page = 1
self.expected_count = expected_count
self.swipes = []
self.clicks = []
def dump_hierarchy(self):
start = min(self.page * 2, len(self.packages) - 3)
visible = self.packages[start : start + 3]
options = []
for index, text in enumerate(visible):
left = 36 + index * 320
options.append(
f'<node text="{text}" clickable="true" '
f'bounds="[{left},1250][{left + 280},1370]" />'
)
return f"""<hierarchy>
<node bounds="[0,0][1080,2340]">
<node class="android.widget.ScrollView" scrollable="true"
bounds="[0,650][1080,2200]">
<node text="券后 ¥5.69" bounds="[300,680][600,740]" />
<node text="款式" bounds="[36,800][180,860]" />
<node text="口罩款" clickable="true" selected="true"
bounds="[36,900][300,1000]" />
<node text="套餐({self.expected_count})"
bounds="[36,1120][240,1180]" />
<node class="androidx.recyclerview.widget.RecyclerView"
scrollable="true" bounds="[24,1200][1056,1420]">
{''.join(options)}
</node>
</node>
</node>
</hierarchy>"""
def swipe(self, x1, y1, x2, y2, duration=0.35):
self.swipes.append((x1, y1, x2, y2, duration))
if abs(x2 - x1) <= abs(y2 - y1):
return
if x1 > x2:
self.page = min(self.page + 1, 2)
else:
self.page = max(self.page - 1, 0)
class FakeClock:
"""测试用时钟:sleep 只推进虚拟时间,不真的等待。"""
@@ -1171,6 +1220,44 @@ class PddCollectParserTest(unittest.TestCase):
self.assertEqual(data["dimensions"][1]["key"], "size")
self.assertEqual(data["dimensions"][1]["name"], "套餐")
def test_horizontal_packages_are_scanned_from_left_to_right_without_clicks(self):
device = HorizontalPackageDevice()
service = PddCollectService(
PddDeviceService(lambda _serial: device),
"USB-001",
"client-001",
sleeper=lambda _seconds: None,
)
result = service._collect_size_dimension(device)
self.assertIsNotNone(result)
self.assertEqual(result.name, "套餐(7)")
self.assertEqual(
[value.text for value in result.values],
list(device.packages),
)
self.assertEqual(device.clicks, [])
self.assertTrue(
all(abs(x2 - x1) > abs(y2 - y1) for x1, y1, x2, y2, _ in device.swipes)
)
def test_package_heading_count_rejects_partial_collection(self):
device = HorizontalPackageDevice(expected_count=8)
service = PddCollectService(
PddDeviceService(lambda _serial: device),
"USB-001",
"client-001",
sleeper=lambda _seconds: None,
)
with self.assertRaises(PddCollectError) as raised:
service._collect_size_dimension(device)
self.assertEqual(raised.exception.code, "PDD_DATA_SPEC_INCOMPLETE")
self.assertEqual(raised.exception.diagnostics["expected_count"], 8)
self.assertEqual(raised.exception.diagnostics["collected_count"], 7)
def test_visible_click_is_fallback_when_page_exposes_no_selection_state(self):
xml_data = keep_only_one_sku(self.spec_xml)
root = ET.fromstring(xml_data)