164 lines
5.6 KiB
TypeScript
164 lines
5.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { calculateHorizontalScrollWindow } from "../horizontalScroll";
|
|
|
|
describe("calculateHorizontalScrollWindow", () => {
|
|
// Basic scenarios
|
|
test("all items fit within available width", () => {
|
|
const result = calculateHorizontalScrollWindow([10, 10, 10], 50, 3, 1);
|
|
expect(result).toEqual({
|
|
startIndex: 0,
|
|
endIndex: 3,
|
|
showLeftArrow: false,
|
|
showRightArrow: false,
|
|
});
|
|
});
|
|
|
|
test("single item selected within view", () => {
|
|
const result = calculateHorizontalScrollWindow([20], 50, 3, 0);
|
|
expect(result).toEqual({
|
|
startIndex: 0,
|
|
endIndex: 1,
|
|
showLeftArrow: false,
|
|
showRightArrow: false,
|
|
});
|
|
});
|
|
|
|
test("selected item at beginning", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 25, 3, 0);
|
|
expect(result.startIndex).toBe(0);
|
|
expect(result.showLeftArrow).toBe(false);
|
|
expect(result.showRightArrow).toBe(true);
|
|
expect(result.endIndex).toBeGreaterThan(0);
|
|
});
|
|
|
|
test("selected item at end", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 25, 3, 4);
|
|
expect(result.endIndex).toBe(5);
|
|
expect(result.showRightArrow).toBe(false);
|
|
expect(result.showLeftArrow).toBe(true);
|
|
});
|
|
|
|
test("selected item beyond visible range scrolls right", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 4);
|
|
expect(result.startIndex).toBeLessThanOrEqual(4);
|
|
expect(result.endIndex).toBeGreaterThan(4);
|
|
});
|
|
|
|
test("selected item before visible range scrolls left", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
// Select last item first (simulates initial scroll to end)
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 0);
|
|
expect(result.startIndex).toBe(0);
|
|
});
|
|
|
|
// Arrow indicators
|
|
test("showLeftArrow when items hidden on left", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 15, 3, 4);
|
|
expect(result.showLeftArrow).toBe(true);
|
|
});
|
|
|
|
test("showRightArrow when items hidden on right", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 15, 3, 0);
|
|
expect(result.showRightArrow).toBe(true);
|
|
});
|
|
|
|
test("no arrows when all items visible", () => {
|
|
const result = calculateHorizontalScrollWindow([10, 10], 50, 3, 0);
|
|
expect(result.showLeftArrow).toBe(false);
|
|
expect(result.showRightArrow).toBe(false);
|
|
});
|
|
|
|
test("both arrows when items hidden on both sides", () => {
|
|
const widths = [10, 10, 10, 10, 10, 10, 10];
|
|
// Select middle item with limited width
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 3);
|
|
// Both arrows may or may not show depending on exact fit
|
|
expect(result.startIndex).toBeLessThanOrEqual(3);
|
|
expect(result.endIndex).toBeGreaterThan(3);
|
|
});
|
|
|
|
// Boundary conditions
|
|
test("empty itemWidths array", () => {
|
|
const result = calculateHorizontalScrollWindow([], 50, 3, 0);
|
|
expect(result).toEqual({
|
|
startIndex: 0,
|
|
endIndex: 0,
|
|
showLeftArrow: false,
|
|
showRightArrow: false,
|
|
});
|
|
});
|
|
|
|
test("single item", () => {
|
|
const result = calculateHorizontalScrollWindow([30], 50, 3, 0);
|
|
expect(result).toEqual({
|
|
startIndex: 0,
|
|
endIndex: 1,
|
|
showLeftArrow: false,
|
|
showRightArrow: false,
|
|
});
|
|
});
|
|
|
|
test("available width is 0", () => {
|
|
const result = calculateHorizontalScrollWindow([10, 10], 0, 3, 0);
|
|
// With 0 width, nothing fits except maybe the selected
|
|
expect(result.startIndex).toBe(0);
|
|
});
|
|
|
|
test("item wider than available width", () => {
|
|
const result = calculateHorizontalScrollWindow([100], 50, 3, 0);
|
|
// Total width > available, but only one item
|
|
expect(result.startIndex).toBe(0);
|
|
expect(result.endIndex).toBe(1);
|
|
});
|
|
|
|
test("all items same width", () => {
|
|
const widths = [10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 25, 3, 2);
|
|
expect(result.startIndex).toBeLessThanOrEqual(2);
|
|
expect(result.endIndex).toBeGreaterThan(2);
|
|
});
|
|
|
|
test("varying item widths", () => {
|
|
const widths = [5, 20, 5, 20, 5];
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 2);
|
|
expect(result.startIndex).toBeLessThanOrEqual(2);
|
|
expect(result.endIndex).toBeGreaterThan(2);
|
|
});
|
|
|
|
test("firstItemHasSeparator adds separator width to first item", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const withSep = calculateHorizontalScrollWindow(widths, 20, 3, 4, true);
|
|
const withoutSep = calculateHorizontalScrollWindow(widths, 20, 3, 4, false);
|
|
// Both should include selected index 4
|
|
expect(withSep.endIndex).toBe(5);
|
|
expect(withoutSep.endIndex).toBe(5);
|
|
});
|
|
|
|
test("selectedIdx in middle of overflow", () => {
|
|
const widths = [10, 10, 10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 25, 3, 3);
|
|
expect(result.startIndex).toBeLessThanOrEqual(3);
|
|
expect(result.endIndex).toBeGreaterThan(3);
|
|
});
|
|
|
|
test("scroll snaps to show selected at left edge", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
// Jump to last item which forces scroll
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 4);
|
|
expect(result.startIndex).toBeLessThanOrEqual(4);
|
|
expect(result.endIndex).toBe(5);
|
|
});
|
|
|
|
test("scroll snaps to show selected at right edge", () => {
|
|
const widths = [10, 10, 10, 10, 10];
|
|
const result = calculateHorizontalScrollWindow(widths, 20, 3, 4);
|
|
expect(result.endIndex).toBe(5);
|
|
expect(result.startIndex).toBeGreaterThan(0);
|
|
});
|
|
});
|