"""Fixture payloads for ``POST /wechatweb/wxFriends/talkerList`` (M2). These records mirror the real field names captured from the live CRM (see the data dictionary §2 会话列表 talker: ``friendWechatId, nickName, remarkName, messageCount, lastChatTime, headUrl, memberCount, analyseResult``). The endpoint is **per-staff-wechat**: the request body carries the ``wechatId`` of the owning staff account, and the response lists that account's recent conversations (direct chats AND group chats — ``memberCount > 0`` ⇒ group). The envelope carries the row list under ``data.page`` with a boolean ``data.hasMore`` flag (no ``total`` field is documented for this endpoint):: {"message":"调用成功","code":"10000","success":true,"traceId":"...", "data":{"page":[ {}, ... ], "hasMore":..}} Because the page-number paginator reuses the empty-page stop signal, the cassette ships the records across two pages plus a terminating empty page: * page 1 -> 2 of the 3 fixture talks, ``hasMore=true`` * page 2 -> the remaining 1 talk, ``hasMore=false`` * (page 3 -> empty ``page`` array, served inline by the test) Records exercise both the direct-message path (``memberCount == 0``) and the group-chat path (``memberCount > 0``) so the orchestrator can distinguish them. """ # The module name uses camelCase deliberately to mirror the upstream endpoint # name (``talkerList``); the M2 spec mandates this exact filename. # ruff: noqa: N999 from __future__ import annotations from typing import Any # The owning staff wechat for this talker stream (the ``wechatId`` request # field). All records below belong to this account's conversation list. OWNER_WECHAT_ID = "wxid_staff_alice01" # --------------------------------------------------------------------------- # Capture-shaped talker (conversation) records (3 total across 2 pages). # --------------------------------------------------------------------------- TALKER_RECORDS: list[dict[str, Any]] = [ { # Direct message (1:1 friend). memberCount == 0. "friendWechatId": "wxid_friend_0001", "nickName": "Alice Wang", "remarkName": "Alice-VIP", "messageCount": 46, "lastChatTime": 1700000000123, "headUrl": "https://wx.qlogo.cn/avatar_alice.png", "memberCount": 0, "displayName": "", "analyseResult": "", }, { # Group chat. memberCount > 0 ⇒ the friendWechatId is a @chatroom id. "friendWechatId": "12345678901@chatroom", "nickName": "VIP客户交流群", "remarkName": "", "messageCount": 4521, "lastChatTime": 1700000000456, "headUrl": "https://wx.qlogo.cn/room_12345678901.png", "memberCount": 3, "displayName": "Alice (group)", "analyseResult": "", }, { # Another direct message — a less active contact. "friendWechatId": "wxid_friend_0009", "nickName": "Quiet Lead", "remarkName": "", "messageCount": 2, "lastChatTime": 1700000000789, "headUrl": "https://wx.qlogo.cn/avatar_quiet.png", "memberCount": 0, "displayName": "", "analyseResult": "", }, ] # Default page size for the fixture (and the scraper). 3 records fill exactly # 2 pages of size 2 plus a terminating empty page. TOTAL = len(TALKER_RECORDS) DEFAULT_PAGE_SIZE = 2 def make_talker_list_response( records: list[dict[str, Any]], *, page_num: int = 1, page_size: int = DEFAULT_PAGE_SIZE, has_more: bool = False, trace_id: str | None = None, ) -> dict[str, Any]: """Build a capture-shaped ``talkerList`` response envelope. Shape (row list under ``data.page``, boolean ``data.hasMore``):: {"message":"调用成功","code":"10000","success":true,"traceId":"...", "data":{"page":[...], "hasMore":..}} """ return { "message": "调用成功", "code": "10000", "success": True, "traceId": trace_id or f"trace-{page_num}", "data": { "page": list(records), "hasMore": has_more, }, }