diff --git a/yunke-server/tests/test_api_moments.py b/yunke-server/tests/test_api_moments.py index 0e238a6..a4f5770 100644 --- a/yunke-server/tests/test_api_moments.py +++ b/yunke-server/tests/test_api_moments.py @@ -77,3 +77,28 @@ async def test_moments_pagination(make_client): 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