1import { describe, expect, it } from "vite-plus/test";
2
3import { CHAT_LIST_ANCHOR_OFFSET, resolveChatListAnchoredEndSpace } from "./chatList.js";
4
5interface Row {
6 readonly id: string;
7 readonly anchorable: boolean;
8}
9
10const rows: ReadonlyArray<Row> = [
11 { id: "first", anchorable: true },
12 { id: "ignored", anchorable: false },
13 { id: "latest", anchorable: true },
14];
15
16const getAnchorId = (row: Row) => (row.anchorable ? row.id : null);
17
18describe("resolveChatListAnchoredEndSpace", () => {
19 it("anchors only the first eligible row", () => {
20 expect(resolveChatListAnchoredEndSpace(rows, "first", getAnchorId)).toEqual({
21 anchorIndex: 0,
22 anchorOffset: CHAT_LIST_ANCHOR_OFFSET,
23 });
24 });
25
26 it("allows a surface to keep the anchor below its own header", () => {
27 expect(
28 resolveChatListAnchoredEndSpace(rows, "first", getAnchorId, {
29 anchorOffset: 132,
30 }),
31 ).toEqual({
32 anchorIndex: 0,
33 anchorOffset: 132,
34 });
35 });
36
37 it("does not reserve end space for later eligible rows", () => {
38 expect(resolveChatListAnchoredEndSpace(rows, "latest", getAnchorId)).toBeUndefined();
39 });
40
41 it("skips ineligible rows before the first anchor", () => {
42 expect(resolveChatListAnchoredEndSpace(rows.slice(1), "latest", getAnchorId)).toEqual({
43 anchorIndex: 1,
44 anchorOffset: CHAT_LIST_ANCHOR_OFFSET,
45 });
46 });
47
48 it("ignores ineligible rows and missing anchors", () => {
49 expect(resolveChatListAnchoredEndSpace(rows, "ignored", getAnchorId)).toBeUndefined();
50 expect(resolveChatListAnchoredEndSpace(rows, "missing", getAnchorId)).toBeUndefined();
51 expect(resolveChatListAnchoredEndSpace(rows, null, getAnchorId)).toBeUndefined();
52 });
53});