test_19_qiwei_docs_live.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. """企微模块 — 台账 / webhook / 消息(真实 roomId + guid,补 test_13 未覆盖接口)"""
  2. import json
  3. import time
  4. import uuid
  5. from pathlib import Path
  6. import pytest
  7. pytestmark = [pytest.mark.integration, pytest.mark.qiwei_live]
  8. FIXTURE = Path(__file__).parent / "fixtures" / "qiwei_webhook_sample.json"
  9. def _live_webhook_payload(live_guid: str, room_id: str, doc_suffix: str) -> dict:
  10. payload = json.loads(FIXTURE.read_text(encoding="utf-8"))
  11. # 毫秒级 + 后缀哈希,避免同群连续 webhook 被去重
  12. base = int(time.time() * 1000) + (hash(doc_suffix) % 100_000)
  13. docid = f"DOC_LIVE_{doc_suffix}"
  14. for i, item in enumerate(payload.get("data", [])):
  15. item["guid"] = live_guid
  16. item["fromRoomId"] = room_id
  17. item["timestamp"] = base + i
  18. if item.get("msgType") == 13:
  19. item["msgData"]["linkUrl"] = (
  20. f"https://doc.weixin.qq.com/txdoc/excel?docid={docid}"
  21. )
  22. return payload, docid
  23. def test_live_webhook_register_room_doc(api, live_guid, live_room_id):
  24. suffix = uuid.uuid4().hex[:8]
  25. payload, docid = _live_webhook_payload(live_guid, live_room_id, suffix)
  26. data = api.assert_success(api.post("/qiwei/webhook", json=payload))
  27. assert data["processedCount"] >= 1
  28. assert data["docLinksFound"] >= 1
  29. doc = api.assert_success(api.get("/qiwei/room-docs", params={"roomId": live_room_id}))
  30. assert doc["roomId"] == live_room_id
  31. assert docid in doc["docId"]
  32. def test_live_messages_list(api, live_guid, live_room_id):
  33. """先 sync 真消息,再查列表(可与 webhook 并存)"""
  34. api.assert_success(
  35. api.post("/qiwei/sync", json={"guid": live_guid, "msgSeq": 0, "limit": 10})
  36. )
  37. msgs = api.assert_success(
  38. api.get("/qiwei/messages", params={"roomId": live_room_id, "limit": 20})
  39. )
  40. assert isinstance(msgs, list)
  41. def test_live_room_docs_list(api, live_room_id):
  42. docs = api.assert_success(api.get("/qiwei/room-docs"))
  43. assert isinstance(docs, list)
  44. assert any(d.get("roomId") == live_room_id for d in docs)
  45. def test_live_room_doc_anomaly_and_resolve(api, live_guid, live_room_id):
  46. """同一真群连续登记两个不同 docid → 多表异常 → 人工解决"""
  47. suffix = uuid.uuid4().hex[:8]
  48. p1, doc1 = _live_webhook_payload(live_guid, live_room_id, f"a{suffix}")
  49. api.assert_success(api.post("/qiwei/webhook", json=p1))
  50. p2, doc2 = _live_webhook_payload(live_guid, live_room_id, f"b{suffix}")
  51. api.assert_success(api.post("/qiwei/webhook", json=p2))
  52. anomalies = api.assert_success(api.get("/qiwei/room-doc-anomalies"))
  53. hit = [
  54. a
  55. for a in anomalies
  56. if a.get("roomId") == live_room_id
  57. and a.get("type") == "multi_doc"
  58. and a.get("newDocId") == doc2
  59. ]
  60. assert hit, f"应产生 multi_doc 异常 newDocId={doc2}, 实际={anomalies}"
  61. resolved = api.assert_success(
  62. api.put(
  63. f"/qiwei/room-doc-anomalies/{live_room_id}/resolve",
  64. json={"newDocId": doc2, "resolution": "keep_new"},
  65. )
  66. )
  67. assert resolved["roomId"] == live_room_id
  68. assert resolved["status"] == "resolved"