test_enrich_research_library.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import importlib.util
  2. from pathlib import Path
  3. import unittest
  4. spec = importlib.util.spec_from_file_location('enrich', Path(__file__).with_name('enrich-research-library.py'))
  5. m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
  6. class ProvenanceTests(unittest.TestCase):
  7. def doc(self, d): return {'data': {'code': 0, 'data': d, 'recordTime': '2026-11-10T12:00:00'}}
  8. def test_exact_review_identity_and_large_id(self):
  9. rows, excluded = m.reviews(self.doc({'comments': [
  10. {'auction': {'aucNumId': '123'}, 'rateId': 12345678901234567890, 'content': '口感有嚼劲'},
  11. {'auction': {'aucNumId': '124'}, 'rateId': 1, 'content': '不属于原商品'}]}), 'taobao', '123')
  12. self.assertEqual(rows[0]['reviewId'], '12345678901234567890')
  13. self.assertEqual(len(rows), 1); self.assertEqual(excluded['REVIEW_PRODUCT_ID_MISMATCH'], 1)
  14. def test_shipping_weight_and_masked_price_not_converted(self):
  15. rows, price = m.detail(self.doc({'product': {'skuId': '123', 'color': '牛肉面6桶装', 'weight': '1.12'}, 'priceFloor': {'price': '5?'}}), 'jd', '123')
  16. self.assertEqual(rows[0]['specText'], '牛肉面6桶装')
  17. self.assertNotIn('netWeightG', rows[0]); self.assertIsNone(price)
  18. def test_sku_choices_separated(self):
  19. d = {'item': {'itemId': '123'}, 'skuBase': {'props': [{'pid': '1', 'name': '口味', 'values': [{'vid': 'a', 'name': '牛肉'}, {'vid': 'b', 'name': '鸡汤'}]}], 'skus': [{'skuId': '7', 'propPath': '1:a'}, {'skuId': '8', 'propPath': '1:b'}]}}
  20. rows, _ = m.detail(self.doc(d), 'taobao', '123')
  21. self.assertEqual([r['specText'] for r in rows], ['口味:牛肉', '口味:鸡汤'])
  22. def test_recommendations_and_title_only_rejected(self):
  23. with self.assertRaisesRegex(ValueError, 'SOCIAL_ID_MISMATCH'): m.social_body(self.doc([{'id': 'other', 'desc': '错配正文'}]), 'xiaohongshu', '123')
  24. with self.assertRaisesRegex(ValueError, 'BODY_ONLY_REPEATS_TITLE'): m.social_body(self.doc([{'id': '123', 'title': '好吃!', 'desc': '好吃'}]), 'xiaohongshu', '123')
  25. def test_empty_bili_description_not_title_fallback(self):
  26. with self.assertRaisesRegex(ValueError, 'UPSTREAM_BODY_EMPTY'): m.social_body(self.doc({'bvid': 'BVx', 'title': '标题', 'desc': ''}), 'bilibili', 'BVx')
  27. def test_bili_recommendations_never_supply_primary_body(self):
  28. d = {'bvid': 'BVx', 'title': '标题', 'desc': '', 'related': [{'bvid': 'BVx', 'desc': '这不是本视频的作者简介'}]}
  29. with self.assertRaisesRegex(ValueError, 'UPSTREAM_BODY_EMPTY'): m.social_body(self.doc(d), 'bilibili', 'BVx')
  30. with self.assertRaisesRegex(ValueError, 'SOCIAL_ID_MISMATCH'): m.social_body(self.doc({'bvid': 'BVother', 'desc': '他人正文', 'related': [d]}), 'bilibili', 'BVx')
  31. def test_placeholder_description_is_not_fulltext(self):
  32. for text in ('-', '——', '...', '暂无简介'):
  33. with self.subTest(text=text), self.assertRaisesRegex(ValueError, 'UPSTREAM_BODY_PLACEHOLDER'):
  34. m.social_body(self.doc({'bvid': 'BVx', 'title': '标题', 'desc': text}), 'bilibili', 'BVx')
  35. def test_primary_web_and_app_shapes(self):
  36. self.assertEqual(m.social_body(self.doc({'videoData': {'bvid': 'BVx', 'title': '标题', 'desc_v2': [{'raw_text': '真实简介'}]}}), 'bilibili', 'BVx'), '真实简介')
  37. self.assertEqual(m.social_body(self.doc([{'note_list': [{'id': '123', 'title': '标题', 'desc': '真实笔记正文'}]}]), 'xiaohongshu', '123'), '真实笔记正文')
  38. self.assertEqual(m.social_body(self.doc({'note_id': '123', 'title': '标题', 'desc': '真实笔记正文'}), 'xiaohongshu', '123'), '真实笔记正文')
  39. def test_nested_xhs_recommendation_rejected(self):
  40. with self.assertRaisesRegex(ValueError, 'SOCIAL_ID_MISMATCH'):
  41. m.social_body(self.doc([{'id': 'other', 'desc': '推荐正文', 'related': [{'id': '123', 'desc': '不能用'}]}]), 'xiaohongshu', '123')
  42. def test_conflicting_xhs_primary_objects_rejected(self):
  43. with self.assertRaisesRegex(ValueError, 'SOCIAL_PRIMARY_OBJECT_CONFLICT'):
  44. m.social_body(self.doc([{'id': '123', 'desc': '原文甲'}, {'id': '123', 'desc': '原文乙'}]), 'xiaohongshu', '123')
  45. def test_http_success_with_no_video_is_not_a_body(self):
  46. with self.assertRaisesRegex(ValueError, 'UPSTREAM_DETAIL_UNAVAILABLE'):
  47. m.social_body(self.doc({'message': 'NO VIDEO'}), 'bilibili', 'BVx')
  48. if __name__ == '__main__': unittest.main()