import { describe, expect, it } from "vitest"; import { FILE_HEADER_HEIGHT } from "./model"; import { buildNativeCanvasSlabs, nativeCanvasSlabsForViewport, nativeCanvasWindowBucket, nativeCanvasWindowTop, nativeStickyHeaderIndices, } from "./native-slabs"; import type { DiffDocumentModel } from "./types"; function modelWithBodies( bodies: Array<{ path: string; bodyTop: number; bottom: number }>, ): DiffDocumentModel { return { files: bodies.map((body, fileIndex) => ({ file: {} as never, fileIndex, path: body.path, top: body.bodyTop - FILE_HEADER_HEIGHT, headerHeight: FILE_HEADER_HEIGHT, bodyTop: body.bodyTop, bodyHeight: body.bottom - body.bodyTop, bottom: body.bottom, gutterWidth: 48, contentWidth: 500, rowStart: 0, rowEnd: 0, isCollapsed: body.bottom === body.bodyTop, })), rows: [], height: bodies.at(-1)?.bottom ?? 0, lineHeight: 20, layout: "unified", wrapLines: false, viewportWidth: 400, }; } describe("native canvas slabs", () => { it("identifies each direct file header child for native sticky scrolling", () => { expect(nativeStickyHeaderIndices(0)).toEqual([]); expect(nativeStickyHeaderIndices(3)).toEqual([1, 3, 5]); }); it("cuts large file bodies into fixed document-positioned slabs", () => { const slabs = buildNativeCanvasSlabs( modelWithBodies([ { path: "small.ts", bodyTop: FILE_HEADER_HEIGHT, bottom: FILE_HEADER_HEIGHT + 200 }, { path: "large.ts", bodyTop: FILE_HEADER_HEIGHT * 2 + 200, bottom: FILE_HEADER_HEIGHT * 2 + 3400, }, ]), 600, ); expect(slabs.map(({ path, top, height }) => ({ path, top, height }))).toEqual([ { path: "small.ts", top: 30, height: 200 }, { path: "large.ts", top: 260, height: 1200 }, { path: "large.ts", top: 1460, height: 1200 }, { path: "large.ts", top: 2660, height: 800 }, ]); }); it("retains only viewport-adjacent slabs and updates on half-viewport boundaries", () => { const slabs = buildNativeCanvasSlabs( modelWithBodies([ { path: "large.ts", bodyTop: FILE_HEADER_HEIGHT, bottom: FILE_HEADER_HEIGHT + 4800 }, ]), 600, ); expect(nativeCanvasSlabsForViewport(slabs, 1700, 600).map((slab) => slab.top)).toEqual([ 30, 1230, 2430, ]); expect(nativeCanvasWindowBucket(899, 600)).toBe(2); expect(nativeCanvasWindowTop(2, 600)).toBe(600); }); });