A8 小红书 (Xhs) — 真机 E2E 测试计划
Status: v0.2 计划 (2026-05-24) — stub A8XhsE2ETest.kt 已落,真机执行需 Mac/Linux + Android 真机 + 真账号;Win dev box 无法运行。
范围
A8 v0.2 端到端覆盖 Xiaohongshu 完整路径:
WebView 登录 → SocialCookieWebViewScreen 提取 cookie (a1 / web_session / webId / xsecappid)
↓
HubLocalViewModel.syncXhs()
↓
XhsLocalCollector.snapshot()
↓ XhsApiClient × 4:
↓ me /api/sns/web/v1/user/me (cookie-only, 无 X-S)
↓ notes /api/sns/web/v2/user_posted (X-S + X-T required)
↓ liked /api/sns/web/v1/note/like/page (X-S + X-T required)
↓ follows /api/sns/web/v1/user/follow/list (X-S + X-T required)
↓ JSON 拼装写 filesDir/.chainlesschain/staging/social-xhs.json
↓
LocalCcRunner.syncAdapter("social-xhs", path)
↓ mksh 起 in-APK cc 子进程
↓ cc hub sync-adapter --input <path> --json
↓ adapter._syncViaSnapshot → registry → 本机 SQLCipher LocalVault
↓
UI 显示 "已同步 N 条 (笔记 + 点赞 + 关注)"前置(一次性)
- 真小红书账号 (账号有 ≥1 篇发布笔记 + ≥1 篇点赞过的笔记 + ≥1 个关注)
- Mac/Linux dev box (Win 不能跑 adb / Android SDK)
- 真 Android 设备
- APK 已 bundle in-APK cc + PDH ≥ 0.3.0
- 网络抓包工具 (Charles / mitmproxy) — 模拟 461 / 风控场景
9 个 E2E 场景
场景 1 — 首次登录成功(happy path)
步骤:
- 打开 ChainlessChain → 个人数据中台 → 本机数据 tab
- 看到"小红书"卡片,状态"未登录"
- 点"登录"→ WebView 加载
https://www.xiaohongshu.com/(banner 推"一键登录",不推扫码) - 用真账号登录 (短信 / 一键登录)
- WebView 跳到
www.xiaohongshu.com主页 → ChainlessChain 命中 isLoginSuccess - 提取 cookie + 调
/api/sns/web/v1/user/me拿 user_id + nickname → 关 WebView
断言:
- WebView 在登录后 ≤ 3s 内自动关闭
- 卡片状态变"已登录
<nickname>" pdh_social_xhsEncryptedSharedPreferences 中cookie/userId/displayName/a1全非空- a1 字段独立持久 (X-S 算法依赖)
场景 2 — 同步 3 类数据成功
前置: 场景 1 已完成
步骤:
- 在卡片点"同步"
- ~10-25s 后 (3 个 X-S 端点 sequential),toast "social-xhs 同步完成 (+N 事件)"
- 卡片显示"上次同步: <时间> (+N 事件)"
断言:
- N ≥ 3 (至少各类 1 条)
- vault 中可见 originalId 前缀
xhs:note:/xhs:liked:/xhs:follow: - 子进程日志含 3 类 fetcher 完成行 (不应有 sentinel "-461" 或 "code 460")
场景 3 — X-S 签名失败 (code 461 / -461)
前置: 已登录但 X-S 算法漂移 (xhs 升级风控算法后 v0.2 算法不再被接受)
模拟:
- Charles 拦
/api/sns/web/v2/user_posted返{ "code": 460, "msg": "invalid signature" } - 或返 HTTP 461
步骤:
- 点"同步"
断言:
- 同步不抛异常 (catch sentinel)
- 卡片显示"X-S 签名失败 — 笔记接口 (code=460)。请提交 issue 或等待 v0.3 算法更新。"
- 其他 2 个端点 (liked / follows) 仍能跑 (degraded mode)
- ingested 数 < 期望,但不为 0
场景 4 — Cookie 过期
前置: 已登录,cookie 主动失效
步骤:
adb shell run-as com.chainlesschain.android rm -rf app_webview/Cookies*- 或等 14 天自然过期
- 点"同步"
断言:
/api/sns/web/v1/user/me返{ "code": -101 }或{ "data": null }- 卡片显示"账号未登录 — cookie 已过期"
- 点"退出登录"清除本地 store
- 点"登录"进 WebView,仍是登录页
场景 5 — WebView 取消登录
步骤:
- 全新装 APK
- 点"登录"进 WebView
- 在小红书登录页不输任何信息,点系统返回键
断言:
- WebView 关闭返回卡片列表
- 状态仍"未登录"
- 无 toast 错误,无 errorMessage
- store 中 cookie / a1 字段空
场景 6 — 部分 fetcher 失败 (一个 5xx)
前置: 已登录,3 fetcher 中 1 个被代理拦截
模拟:
- Charles 规则: 拦截
/api/sns/web/v1/user/follow/list返 503,其他放行
步骤:
- 点"同步"
断言:
- 同步完成不抛异常
- 卡片显示"+M 事件",M < 总数 (缺 follows 那部分)
- lastErrorCode 透出 503
- notes / liked 正常入库
场景 7 — 反复同步幂等性
前置: 已登录 + 已同步过一次
步骤:
- 立即再点"同步"
- 再点一次
断言:
- 三次 sync 后
vault.queryItems()数量不变 (同 noteId 走 UPSERT) - 三次 sync 后
vault.queryPersons()数量不变 (关注的人去重) - events 表累积 3 倍 (每次 sync 一次 browse-like)
- 子进程日志中 originalId 在 raw_events 表有 dedup
场景 8 — EncryptedSharedPreferences keystore corruption
模拟: 改 pdh_social_xhs.xml 让 AES-256-GCM 解密失败
步骤:
adb shell进 app data dir,备份pdh_social_xhs.xml- 手改 xml 文件 1 byte
- 重启 app
断言:
- App 不 crash
- 小红书卡片显"未登录"
- Timber log 含 "XhsCredentialsStore: read failed"
- 用户能重新登录恢复
场景 9 — 退出登录 + 重新登录
步骤:
- 已登录点"退出登录"
- 卡片状态变"未登录"
- 点"登录"
- 重新登录同一账号
- 同步
断言:
- 退出后 EncryptedSharedPreferences 中 cookie / userId / a1 全空
- 重新登录 userId 同上次
- 同步成功
执行方式
- 手动: 按 9 场景逐一跑,每个 ~5-10 分钟,总 ~1.5h
- 自动化: 暂不可 (小红书登录需短信 / 扫码)
- CI: 仅跑场景 5 + 8 (非真账号);其余手动
反爬 caveats
- X-S 算法每月可能 rotate — 如果场景 3 在新版本机器上是"基线"现象 (而非异常),说明 v0.2 算法已腐烂,需升 v0.3
- a1 cookie 在 WebView 登录后稳定,但每登一次都会 rotate;store 持久的是登录时刻的 a1
- 461 short-band 触发后短 IP 封禁 5-15 分钟,测试间留 buffer
stub 占位
androidTest/.../A8XhsE2ETest.kt 9 个测试方法已 @Ignore 占位,每个含 TODO 链接到本计划对应章节。
不在本 plan 范围
- v0.3 X-S 算法升级 (引入 b1 + a1.tail)
- 笔记内容深度解析 (当前只入 note 元数据,正文 v0.3 加 OCR + 长文截取)
- 私信 / 评论采集 (隐私敏感,v1.0 + 用户显式同意 gate)
- 性能 perf 测试 (单独 plan)
关联文档
docs/design/A8_Bilibili_E2E_Plan.md— 同 v0.1 模板,差异点在 X-S 签名层docs/design/Adapter_Social_Cookie.md— A8 通用设计- memory
pdh_social_collector_test_gap_audit.md— 4-platform / 33 JVM 案例已落,E2E 仍 stub - memory
pdh_social_webview_deeplink_cookie_capture.md— WebView 一键登录 deep-link 协议
