Files
anomalyco_opencode/packages/ui/src/components/scroll-view.test.ts
opencode-agent[bot] e916b99742 chore: merge dev into v2 (#37370)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com>
Co-authored-by: Brendan Allan <git@brendonovich.dev>
Co-authored-by: James Long <longster@gmail.com>
Co-authored-by: James Long <jlongster@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Jay <53023+jayair@users.noreply.github.com>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
Co-authored-by: Dustin Deus <deusdustin@gmail.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: 冯基魁 <56265583+fengjikui@users.noreply.github.com>
Co-authored-by: opencode <opencode@sst.dev>
Co-authored-by: Frank <frank@anoma.ly>
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
Co-authored-by: Kit Langton <kit.langton@gmail.com>
Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com>
Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com>
Co-authored-by: Victor Navarro <vn4varro@gmail.com>
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: Dax <mail@thdxr.com>
Co-authored-by: Nabs <nabil@instafork.com>
Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
Co-authored-by: AidenGeunGeun <eastlandwyvern@gmail.com>
Co-authored-by: Mark <geraint0923@users.noreply.github.com>
Co-authored-by: Jay <air@live.ca>
Co-authored-by: BB84 <110078428+BB-84C@users.noreply.github.com>
2026-07-16 15:44:26 -05:00

91 lines
3.2 KiB
TypeScript

import { describe, expect, test } from "bun:test"
import { canScrollKey, scrollKey, scrollTopFromThumbPointer } from "./scroll-view"
describe("scrollKey", () => {
test("maps plain navigation keys", () => {
expect(scrollKey({ key: "PageDown", altKey: false, ctrlKey: false, metaKey: false, shiftKey: false })).toBe(
"page-down",
)
expect(scrollKey({ key: "ArrowUp", altKey: false, ctrlKey: false, metaKey: false, shiftKey: false })).toBe("up")
})
test("ignores modified keybinds", () => {
expect(
scrollKey({ key: "ArrowDown", altKey: false, ctrlKey: false, metaKey: true, shiftKey: false }),
).toBeUndefined()
expect(scrollKey({ key: "PageUp", altKey: false, ctrlKey: true, metaKey: false, shiftKey: false })).toBeUndefined()
expect(scrollKey({ key: "End", altKey: false, ctrlKey: false, metaKey: false, shiftKey: true })).toBeUndefined()
})
test("maps space and shift-space directions", () => {
expect(scrollKey({ key: " ", altKey: false, ctrlKey: false, metaKey: false, shiftKey: false })).toBe("page-down")
expect(scrollKey({ key: " ", altKey: false, ctrlKey: false, metaKey: false, shiftKey: true })).toBe("page-up")
})
})
describe("canScrollKey", () => {
const element = (scrollTop: number, clientHeight = 100, scrollHeight = 300) =>
({ scrollTop, clientHeight, scrollHeight }) as HTMLElement
test("owns upward keys only above the top boundary", () => {
expect(canScrollKey(element(50), "page-up")).toBe(true)
expect(canScrollKey(element(0), "page-up")).toBe(false)
})
test("owns downward keys only before the bottom boundary", () => {
expect(canScrollKey(element(50), "page-down")).toBe(true)
expect(canScrollKey(element(200), "page-down")).toBe(false)
expect(canScrollKey(element(0, 100, 100), "page-down")).toBe(false)
})
})
describe("scrollTopFromThumbPointer", () => {
test("keeps downward thumb movement monotonic when content height changes", () => {
const first = scrollTopFromThumbPointer({
pointer: 300,
viewportTop: 100,
grabOffset: 12,
clientHeight: 600,
scrollHeight: 6_000,
thumbHeight: 60,
})
const second = scrollTopFromThumbPointer({
pointer: 320,
viewportTop: 100,
grabOffset: 12,
clientHeight: 600,
scrollHeight: 60_000,
thumbHeight: 32,
})
expect(second).toBeGreaterThan(first)
})
test("clamps pointer positions to the scroll range", () => {
const input = {
viewportTop: 100,
grabOffset: 12,
clientHeight: 600,
scrollHeight: 6_000,
thumbHeight: 60,
}
expect(scrollTopFromThumbPointer({ ...input, pointer: 0 })).toBe(0)
expect(scrollTopFromThumbPointer({ ...input, pointer: 1_000 })).toBe(5_400)
})
test("uses scrollClientHeight when the thumb track differs from the viewport", () => {
const input = {
pointer: 400,
viewportTop: 100,
grabOffset: 0,
clientHeight: 400,
scrollClientHeight: 800,
scrollHeight: 8_000,
thumbHeight: 40,
}
// track usable = 400 - 16 - 40 = 344; thumbTop = 400 - 100 - 8 = 292
// maxScroll = 8000 - 800 = 7200 → 292/344 * 7200
expect(scrollTopFromThumbPointer(input)).toBeCloseTo((292 / 344) * 7200)
})
})