"""SurugayaClient._parse_other_shop_list 的解析单元测试。 固定 HTML 节选自真实的 /product/other/{goods_id} 页面结构(tbl_all 标签页), 覆盖官方自营行(无 tenpo_cd/无评分)与加盟店/市场店铺行(含 tenpo_cd/评分)。 """ from __future__ import annotations from selectolax.parser import HTMLParser from app.services.surugaya_client import SurugayaClient OTHER_SHOP_HTML = """

1,370円

中古箱・ジャケット・ケース不備(中)

5.0(1334件)
  • 1日〜3日以内に発送します

2,000円

中古

  • 1日〜7日以内に発送します

2,744円

新品新古品(店頭在庫品) ※ショップ情報をご確認下さい

5.0(46件)
  • 2日〜7日以内に発送します

980円

中古

4.5(10件)
  • 1日〜3日以内に発送します
""" def test_parse_other_shop_list_extracts_all_rows() -> None: """四行分别为:加盟店、官方自营、市场店铺、无 data-zaiko_data 的加盟店,均应被正确解析。""" tree = HTMLParser(OTHER_SHOP_HTML) items = SurugayaClient._parse_other_shop_list(tree) assert len(items) == 4 def test_parse_other_shop_list_franchise_row() -> None: """加盟店行:tenpo_cd/店名/评分/价格/发货时效均应正确填充。""" tree = HTMLParser(OTHER_SHOP_HTML) item = SurugayaClient._parse_other_shop_list(tree)[0] assert item.tenpo_cd == "400451" assert item.is_official is False assert item.shop_name == "駿河屋 山口大学前店" assert item.shop_url == "https://www.suruga-ya.jp/shop/400451" assert item.price == 1370 assert item.condition == "中古箱・ジャケット・ケース不備(中)" assert item.branch_number == "0003" assert item.rating_score == "5.0" assert item.rating_count == 1334 assert item.shipping_note == "1日〜3日以内に発送します" assert item.detail_url == ( "https://www.suruga-ya.jp/product/detail/220035970?tenpo_cd=400451&branch_number=0003" ) def test_parse_other_shop_list_official_row_has_no_tenpo_cd() -> None: """官方自营行:无 /shop/ 链接、tenpo_cd 为空、is_official 应为 True,且无评分。""" tree = HTMLParser(OTHER_SHOP_HTML) item = SurugayaClient._parse_other_shop_list(tree)[1] assert item.tenpo_cd == "" assert item.is_official is True assert item.shop_name == "駿河屋" assert item.price == 2000 assert item.rating_score == "" assert item.rating_count == 0 def test_parse_other_shop_list_marketplace_row() -> None: """市场店铺行:与加盟店行结构一致,同样应正确解析。""" tree = HTMLParser(OTHER_SHOP_HTML) item = SurugayaClient._parse_other_shop_list(tree)[2] assert item.tenpo_cd == "410118" assert item.is_official is False assert item.shop_name == "玉光堂 駿河屋マーケットプレイス店" assert item.price == 2744 assert item.rating_score == "5.0" assert item.rating_count == 46 def test_parse_other_shop_list_branch_number_falls_back_to_detail_url() -> None: """无 ajax-campaign-placeholder(无 data-zaiko_data)时,branch_number 应从 detail_url 查询参数回退提取。""" tree = HTMLParser(OTHER_SHOP_HTML) item = SurugayaClient._parse_other_shop_list(tree)[3] assert item.branch_number == "0003" assert item.detail_url == ( "https://www.suruga-ya.jp/product/detail/602274031?tenpo_cd=400567&branch_number=0003" ) def test_parse_other_shop_list_empty_html_returns_empty_list() -> None: """页面结构不包含 tbl_all 时(如解析失败/改版),应返回空列表而非抛异常。""" tree = HTMLParser("no table here") assert SurugayaClient._parse_other_shop_list(tree) == []