1import { LegendList, type LegendListRef } from "@legendapp/list/react";
2import { createRef, useState, type RefObject } from "react";
3import { expect, it } from "vite-plus/test";
4import { act, render } from "../../test/render";
5import { useLegendListRef } from "./useLegendListRef";
6
7function ListProbe({
8 items,
9 listRef,
10}: {
11 items: string[];
12 listRef: RefObject<LegendListRef | null>;
13}) {
14 const [edges, setEdges] = useState("");
15 const ref = useLegendListRef(listRef, () => {
16 const state = listRef.current?.getState();
17 if (state) setEdges(`${state.isAtStart}:${state.isAtEnd}`);
18 });
19 return (
20 <>
21 <output aria-label="List edges">{edges}</output>
22 <LegendList
23 ref={ref}
24 data={items}
25 keyExtractor={(item) => item}
26 renderItem={({ item }) => <div style={{ height: 40 }}>{item}</div>}
27 style={{ height: 120, width: 300 }}
28 />
29 </>
30 );
31}
32
33it("refreshes list edges after content shrinks without scrolling and after the list reopens", async () => {
34 const listRef = createRef<LegendListRef | null>();
35 const items = Array.from({ length: 20 }, (_, index) => `Row ${index}`);
36 await using screen = await render(<ListProbe items={items} listRef={listRef} />);
37 await expect.element(screen.getByLabelText("List edges")).toHaveTextContent("true:false");
38 await act(() => {
39 void listRef.current!.scrollToEnd({ animated: false });
40 });
41 await expect.element(screen.getByLabelText("List edges")).toHaveTextContent("false:true");
42 await screen.rerender(<ListProbe items={["Only row"]} listRef={listRef} />);
43 await expect.element(screen.getByLabelText("List edges")).toHaveTextContent("true:true");
44 await screen.rerender(<></>);
45 expect(listRef.current).toBeNull();
46 await screen.rerender(<ListProbe items={items} listRef={listRef} />);
47 await expect.element(screen.getByLabelText("List edges")).toHaveTextContent("true:false");
48});