Skip to content
Source
Sign inSign up

useCodeViewScrollRestore.test.ts

81 lines2.7 KB

1import type { CodeViewScrollTarget } from "@pierre/diffs";
2import { describe, expect, it } from "vite-plus/test";
3​
4import { createCodeViewScrollRestore } from "./useCodeViewScrollRestore";
5​
6function viewer(scrollHeight: number, height = 500) {
7 const instance = { scrollHeight, height, getHeight: () => 0, getScrollHeight: () => 0 };
8 instance.getHeight = () => instance.height;
9 instance.getScrollHeight = () => instance.scrollHeight;
10 const scrolls: CodeViewScrollTarget[] = [];
11 return {
12 instance,
13 scrolls,
14 getInstance: () => instance,
15 scrollTo: (target: CodeViewScrollTarget) => scrolls.push(target),
16 };
18​
19function mount(
20 scopeKey: string,
21 view: ReturnType<typeof viewer>,
22 settled = true,
23 loadMore: (() => void) | null = null,
24) {
25 const restore = createCodeViewScrollRestore();
26 restore.update(scopeKey, settled, loadMore);
27 restore.attach(view);
28 return restore;
30​
31describe("createCodeViewScrollRestore", () => {
32 it("puts a remounted viewer back at its scope's position, not another scope's", () => {
33 const first = viewer(10_000);
34 mount("thread-a", first).onScroll(4000, first.instance);
35 const other = viewer(10_000);
36 mount("thread-b", other).onScroll(1200, other.instance);
37​
38 const again = viewer(10_000);
39 mount("thread-a", again);
40 // Pierre subtracts the 32px sticky header from an unclamped position target.
41 expect(again.scrolls).toEqual([{ type: "position", position: 4032 }]);
42 });
43​
44 it("loads more files until the position is reachable, then gives up once none remain", () => {
45 const first = viewer(10_000);
46 mount("thread-c", first).onScroll(4000, first.instance);
47​
48 const loading = viewer(700);
49 let batches = 0;
50 const restore = mount("thread-c", loading, false, () => {
51 batches += 1;
52 });
53 restore.onScroll(0, loading.instance);
54 restore.flush();
55 expect(loading.scrolls).toEqual([]);
56 expect(batches).toBe(2);
57 loading.instance.scrollHeight = 10_000;
58 restore.flush();
59 restore.flush();
60 expect(loading.scrolls).toEqual([{ type: "position", position: 4032 }]);
61​
62 const shrunk = viewer(2000);
63 const settling = mount("thread-c", shrunk, false);
64 settling.flush();
65 expect(shrunk.scrolls).toEqual([]);
66 settling.update("thread-c", true, null);
67 settling.flush();
68 expect(shrunk.scrolls).toEqual([{ type: "position", position: 1500 }]);
69 });
70​
71 it("forgets a position that a reveal or collapsing every file replaced", () => {
72 const first = viewer(10_000);
73 const restore = mount("thread-d", first);
74 restore.onScroll(4000, first.instance);
75 restore.discard();
76​
77 const again = viewer(10_000);
78 mount("thread-d", again);
79 expect(again.scrolls).toEqual([]);
80 });
81});