"""Fixture payloads for ``POST /wechatweb/chatroom/getChatroomList`` (M2). These records mirror the real field names captured from the live CRM (see the data dictionary §2: ``chatRoomId(@chatroom), chatRoomName, memberCount, memberIds(分号分隔全部成员wxid), headImageUrl, wechatId/wechatNickName(归属), userName/userPhone(群主员工), messageCount/ownMessageCount, lossMembers/ addMembers, lastChatTime/updateTime``; total=1515). The envelope is the same flat shape as ``wxUser/list`` (no ``basicResult`` wrapper): pagination fields sit directly under ``data``:: {"message":"调用成功","code":"10000","success":true,"traceId":"...", "data":{"data":[...], "total":.., "page":.., "pageCount":..}} The cassette ships three records across two pages so a test can drive the page-number paginator across the empty-page stop signal: * page 1 -> 2 of the 3 fixture records, ``total=3`` * page 2 -> the remaining 1 record, ``total=3`` * (page 3 -> empty ``data`` array, served inline by the test) Records carry every field with a target ``ChatGroup`` column so the test can assert a full mapping end-to-end. The ``memberIds`` field is the semicolon-joined member wxid list; record 2 deliberately includes a trailing empty segment (``"...;"``) so the parser's drop-empties path is exercised. """ # The module name mirrors the upstream endpoint name (``chatroom``); the M2 # spec mandates this exact filename. from __future__ import annotations from typing import Any # --------------------------------------------------------------------------- # Capture-shaped chatroom records (3 total across 2 pages). # --------------------------------------------------------------------------- CHATROOM_RECORDS: list[dict[str, Any]] = [ { "chatRoomId": "12345678901@chatroom", "chatRoomName": "VIP客户交流群", "memberCount": 3, # 3 members, no empties -> member_ids_list length 3. "memberIds": "wxid_member_a1;wxid_member_a2;csf7169708", "headImageUrl": "https://wx.qlogo.cn/room_12345678901.png", "wechatId": "wxid_staff_alice01", "wechatNickName": "Alice WeChat", "userId": "staff_user_001", "userName": "Alice Wang", "userPhone": "13800000001", "messageCount": 4521, "ownMessageCount": 1204, "lossMembers": 2, "addMembers": 5, "lastChatTime": 1700000000123, "updateTime": 1700000001000, "version": "v1.20260731.room1", }, { "chatRoomId": "98765432109@chatroom", "chatRoomName": "华东销售大群", "memberCount": 2, # Trailing empty segment -> member_ids_list length 2 (empties dropped). "memberIds": "wxid_member_b1;wxid_member_b2;", "headImageUrl": "https://wx.qlogo.cn/room_98765432109.png", "wechatId": "wxid_staff_bob02", "wechatNickName": "Bob WeChat", "userId": "staff_user_002", "userName": "Bob Chen", "userPhone": "13800000002", "messageCount": 9821, "ownMessageCount": 211, "lossMembers": 0, "addMembers": 1, "lastChatTime": 1700000000456, "updateTime": 1700000000800, "version": "v1.20260731.room2", }, { # A group whose owner has no resolved staff id (userId None) — the # scraper must still yield it; the repo must still upsert its members. "chatRoomId": "55555555555@chatroom", "chatRoomName": "External Coordination", "memberCount": 1, "memberIds": "wxid_member_c1", "headImageUrl": "https://wx.qlogo.cn/room_55555555555.png", "wechatId": "wxid_staff_orphan04", "wechatNickName": "Orphan WeChat", "userId": None, "userName": None, "userPhone": None, "messageCount": 12, "ownMessageCount": 0, "lossMembers": 0, "addMembers": 0, "lastChatTime": 1700000000789, "updateTime": 1700000000900, "version": "v1.20260731.room3", }, ] # Default page size for the fixture (and the scraper). total=3 means the # fixture fills exactly 2 pages of size 2 plus a terminating empty page. TOTAL = len(CHATROOM_RECORDS) DEFAULT_PAGE_SIZE = 2 def make_chatroom_list_response( records: list[dict[str, Any]], *, total: int, page_num: int = 1, page_size: int = DEFAULT_PAGE_SIZE, trace_id: str | None = None, ) -> dict[str, Any]: """Build a capture-shaped ``getChatroomList`` response envelope. Shape (no ``basicResult`` wrapper; pagination fields directly under ``data``):: {"message":"调用成功","code":"10000","success":true,"traceId":"...", "data":{"data":[...], "total":.., "page":.., "pageCount":..}} """ return { "message": "调用成功", "code": "10000", "success": True, "traceId": trace_id or f"trace-{page_num}", "data": { "data": list(records), "total": total, "page": page_num, "pageCount": ( (total + page_size - 1) // page_size if page_size else 1 ), }, }