"""Tests for GET /api/moments — 员工朋友圈帖子列表(create_time desc)+账号头部。""" from __future__ import annotations from sqlalchemy.ext.asyncio import AsyncSession from app.db.models import MomentsPost, WechatAccount STAFF = "wxid_o" async def test_moments_list_desc_with_header(make_client): """按 create_time desc 只返回该员工帖子;header 带账号昵称/头像/别名。""" async def seed(s: AsyncSession): s.add(WechatAccount(wx_id=STAFF, nick_name="员工昵称", raw_json={"headImageUrl": "https://wx.qlogo.cn/a/0"})) s.add(MomentsPost(id="p1", wechat_id=STAFF, content="新帖", create_time=200)) s.add(MomentsPost(id="p2", wechat_id=STAFF, content="旧帖", create_time=100)) s.add(MomentsPost(id="p3", wechat_id="wxid_other", content="别人", create_time=300)) await s.commit() client = await make_client(seed) r = await client.get("/api/moments", params={"wechat_id": STAFF, "page": 1, "page_size": 10}) assert r.status_code == 200 body = r.json() assert body["header"] == {"nickname": "员工昵称", "avatar": "https://wx.qlogo.cn/a/0", "alias": None} assert [p["id"] for p in body["items"]] == ["p1", "p2"] # create_time desc assert body["total"] == 2 async def test_moments_empty_staff(make_client): """无帖子:header 仍返回账号信息,items 空。""" async def seed(s: AsyncSession): s.add(WechatAccount(wx_id=STAFF, nick_name="员工昵称", raw_json={"headImageUrl": "https://wx.qlogo.cn/a/0"})) await s.commit() client = await make_client(seed) r = await client.get("/api/moments", params={"wechat_id": STAFF}) assert r.status_code == 200 body = r.json() assert body["items"] == [] and body["total"] == 0 assert body["header"]["nickname"] == "员工昵称" async def test_moments_unknown_staff(make_client): """员工不存在:header 全 None,items 空——不 404(前端资料卡兜底)。""" async def seed(s: AsyncSession): await s.commit() client = await make_client(seed) r = await client.get("/api/moments", params={"wechat_id": "wxid_ghost"}) assert r.status_code == 200 body = r.json() assert body["header"] == {"nickname": None, "avatar": None, "alias": None} assert body["items"] == [] and body["total"] == 0 async def test_moments_pagination(make_client): """3 帖 page_size=2:第 1 页 2 条(p1,p2),第 2 页 1 条(p3),total 恒 3。""" async def seed(s: AsyncSession): s.add(WechatAccount(wx_id=STAFF, nick_name="员工昵称", alias="al_o")) s.add_all([ MomentsPost(id=f"p{i}", wechat_id=STAFF, create_time=300 - i * 100) for i in range(1, 4) ]) await s.commit() client = await make_client(seed) b1 = (await client.get("/api/moments", params={"wechat_id": STAFF, "page": 1, "page_size": 2})).json() b2 = (await client.get("/api/moments", params={"wechat_id": STAFF, "page": 2, "page_size": 2})).json() assert [p["id"] for p in b1["items"]] == ["p1", "p2"] assert [p["id"] for p in b2["items"]] == ["p3"] assert b1["total"] == b2["total"] == 3 # alias 非空时映射到 header(列直读) assert b1["header"]["alias"] == "al_o" async def test_moments_same_create_time_tiebreak_id_asc(make_client): """同 create_time(秒级来源×1000 必然同值)→ 按 id 升序稳定排列。 锁死分页稳定契约:tie-break 缺失会让同秒帖跨页漂移(每页 offset 重查 时顺序抖动 → 重复/丢帖)。任务 6 评审遗留补测。 """ async def seed(s: AsyncSession): s.add(WechatAccount(wx_id=STAFF, nick_name="员工昵称")) s.add_all([ MomentsPost(id="pz", wechat_id=STAFF, create_time=200, content="z"), MomentsPost(id="pa", wechat_id=STAFF, create_time=200, content="a"), MomentsPost(id="pb", wechat_id=STAFF, create_time=200, content="b"), ]) await s.commit() client = await make_client(seed) b1 = (await client.get("/api/moments", params={"wechat_id": STAFF, "page": 1, "page_size": 2})).json() b2 = (await client.get("/api/moments", params={"wechat_id": STAFF, "page": 2, "page_size": 2})).json() # create_time desc 全并列 → id 升序断尾:pa, pb | pz assert [p["id"] for p in b1["items"]] == ["pa", "pb"] assert [p["id"] for p in b2["items"]] == ["pz"] assert b1["total"] == b2["total"] == 3