fix: 兼容非滚动面板静态尺码采集 (#177)
This commit is contained in:
@@ -1858,6 +1858,11 @@ class PddCollectService:
|
|||||||
"PDD_DATA_SPEC_INCOMPLETE",
|
"PDD_DATA_SPEC_INCOMPLETE",
|
||||||
f"无法建立第二规格续页上下文:{size_name}",
|
f"无法建立第二规格续页上下文:{size_name}",
|
||||||
)
|
)
|
||||||
|
static_dimension = self._non_scrollable_second_dimension(
|
||||||
|
xml_data, initial_size_dimension
|
||||||
|
)
|
||||||
|
if static_dimension is not None:
|
||||||
|
return static_dimension
|
||||||
continuation = self._build_second_dimension_context(
|
continuation = self._build_second_dimension_context(
|
||||||
xml_data, initial_size_dimension
|
xml_data, initial_size_dimension
|
||||||
)
|
)
|
||||||
@@ -1958,6 +1963,51 @@ class PddCollectService:
|
|||||||
tuple(DimensionValue(text, available) for text, available in sizes.items()),
|
tuple(DimensionValue(text, available) for text, available in sizes.items()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _non_scrollable_second_dimension(
|
||||||
|
self,
|
||||||
|
xml_data: str | bytes,
|
||||||
|
dimension: SpecDimension,
|
||||||
|
) -> Optional[SpecDimension]:
|
||||||
|
"""强证据确认非滚动面板时,返回当前树中的完整第二规格。"""
|
||||||
|
|
||||||
|
root = _parse_xml(xml_data)
|
||||||
|
region, _ = self._second_dimension_region(root, dimension)
|
||||||
|
if region is not None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
parents = {child: parent for parent in root.iter() for child in parent}
|
||||||
|
if _find_non_scrollable_spec_panel(root, parents) is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
values: dict[str, bool] = {}
|
||||||
|
for value in dimension.values:
|
||||||
|
option_text = self._second_dimension_option_text(value.text)
|
||||||
|
if option_text is None:
|
||||||
|
continue
|
||||||
|
values[option_text] = values.get(option_text, False) or value.available
|
||||||
|
|
||||||
|
expected_count = self._dimension_expected_count(dimension.name)
|
||||||
|
if expected_count is not None and len(values) < expected_count:
|
||||||
|
raise PddCollectError(
|
||||||
|
"PDD_DATA_SPEC_INCOMPLETE",
|
||||||
|
f"{dimension.name}应有 {expected_count} 个选项,实际只采到 {len(values)} 个",
|
||||||
|
{
|
||||||
|
"dimension_name": dimension.name,
|
||||||
|
"expected_count": expected_count,
|
||||||
|
"collected_count": len(values),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if not values:
|
||||||
|
return None
|
||||||
|
return SpecDimension(
|
||||||
|
"size",
|
||||||
|
dimension.name,
|
||||||
|
tuple(
|
||||||
|
DimensionValue(text, available)
|
||||||
|
for text, available in values.items()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def _move_second_dimension_to_start(
|
def _move_second_dimension_to_start(
|
||||||
self, device: Any, xml_data: str
|
self, device: Any, xml_data: str
|
||||||
) -> tuple[str, bool]:
|
) -> tuple[str, bool]:
|
||||||
|
|||||||
@@ -813,6 +813,74 @@ class PddCollectParserTest(unittest.TestCase):
|
|||||||
[item.name for item in result.dimensions],
|
[item.name for item in result.dimensions],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_collects_static_sizes_from_non_scrollable_submit_hint_panel(self):
|
||||||
|
device = FakeCollectDevice(self.home_xml, self.submit_hint_spec_xml)
|
||||||
|
device.opened_url = (
|
||||||
|
"https://mobile.yangkeduo.com/goods.html?goods_id=123"
|
||||||
|
)
|
||||||
|
device.panel_open = True
|
||||||
|
service = PddCollectService(
|
||||||
|
PddDeviceService(lambda _serial: device),
|
||||||
|
"USB-001",
|
||||||
|
"client-001",
|
||||||
|
sleeper=lambda _seconds: None,
|
||||||
|
)
|
||||||
|
|
||||||
|
dimension = service._collect_size_dimension(device)
|
||||||
|
|
||||||
|
self.assertIsNotNone(dimension)
|
||||||
|
self.assertEqual(dimension.name, "尺码")
|
||||||
|
self.assertEqual(
|
||||||
|
[value.text for value in dimension.values],
|
||||||
|
["M", "L"],
|
||||||
|
)
|
||||||
|
self.assertEqual(device.swipes, [])
|
||||||
|
|
||||||
|
def test_static_sizes_keep_explicit_count_validation(self):
|
||||||
|
spec_xml = self.submit_hint_spec_xml.replace(
|
||||||
|
'text="尺码" bounds=', 'text="尺码(3)" bounds=', 1
|
||||||
|
)
|
||||||
|
device = FakeCollectDevice(self.home_xml, spec_xml)
|
||||||
|
device.opened_url = (
|
||||||
|
"https://mobile.yangkeduo.com/goods.html?goods_id=123"
|
||||||
|
)
|
||||||
|
device.panel_open = True
|
||||||
|
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"], 3)
|
||||||
|
self.assertEqual(raised.exception.diagnostics["collected_count"], 2)
|
||||||
|
|
||||||
|
def test_static_sizes_require_strong_non_scrollable_panel_evidence(self):
|
||||||
|
snapshot = parse_spec_panel(self.submit_hint_spec_xml)
|
||||||
|
dimension = next(
|
||||||
|
item for item in snapshot.dimensions if item.key == "size"
|
||||||
|
)
|
||||||
|
incomplete_evidence_xml = self.submit_hint_spec_xml.replace(
|
||||||
|
'class="android.widget.EditText"',
|
||||||
|
'class="android.widget.TextView"',
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
service = PddCollectService(
|
||||||
|
PddDeviceService(lambda _serial: object()),
|
||||||
|
"USB-001",
|
||||||
|
"client-001",
|
||||||
|
)
|
||||||
|
|
||||||
|
result = service._non_scrollable_second_dimension(
|
||||||
|
incomplete_evidence_xml, dimension
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
def test_isolated_submit_hint_is_not_a_spec_panel(self):
|
def test_isolated_submit_hint_is_not_a_spec_panel(self):
|
||||||
xml_data = """<hierarchy>
|
xml_data = """<hierarchy>
|
||||||
<node package="com.xunmeng.pinduoduo"
|
<node package="com.xunmeng.pinduoduo"
|
||||||
|
|||||||
Reference in New Issue
Block a user