Files
Termix/plugins/remote-desktop/tests/frontend/guacamole-scroll.test.ts
T

82 lines
2.2 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import {
clampPendingScrollClicks,
createScrollCoalescer,
isScrollButtonState,
MAX_SCROLL_CLICKS_PER_FLUSH,
SCROLL_FLUSH_INTERVAL_MS,
takeScrollClicks,
} from "../../src/frontend/guacamole-scroll.js";
describe("guacamole scroll coalescing", () => {
it("caps a click flood so a laggy tunnel cannot queue a backlog", () => {
expect(clampPendingScrollClicks(0, 40)).toBe(MAX_SCROLL_CLICKS_PER_FLUSH);
expect(clampPendingScrollClicks(0, -40)).toBe(-MAX_SCROLL_CLICKS_PER_FLUSH);
expect(takeScrollClicks(20)).toEqual({
clicks: MAX_SCROLL_CLICKS_PER_FLUSH,
direction: 1,
});
});
it("sends the first notch immediately and drops later clicks in the same burst", () => {
const send = vi.fn();
let now = 1_000;
const scheduled: Array<{ fn: () => void; ms: number }> = [];
const coalescer = createScrollCoalescer(
send,
() => now,
(fn, ms) => {
scheduled.push({ fn, ms });
return scheduled.length;
},
() => {},
);
coalescer.notePointer({
x: 12,
y: 34,
left: false,
middle: false,
right: false,
up: false,
down: false,
});
for (let i = 0; i < 20; i++) coalescer.ingestClick(1);
const firstBurst = send.mock.calls.map(([state]) => state);
expect(firstBurst).toEqual([
{
x: 12,
y: 34,
left: false,
middle: false,
right: false,
up: false,
down: true,
},
{
x: 12,
y: 34,
left: false,
middle: false,
right: false,
up: false,
down: false,
},
]);
send.mockClear();
now += SCROLL_FLUSH_INTERVAL_MS;
expect(scheduled).toHaveLength(1);
scheduled[0].fn();
expect(send.mock.calls).toHaveLength(MAX_SCROLL_CLICKS_PER_FLUSH * 2);
coalescer.dispose();
});
it("recognizes only the scroll buttons as coalesced input", () => {
expect(isScrollButtonState({ up: true, down: false })).toBe(true);
expect(isScrollButtonState({ up: false, down: true })).toBe(true);
expect(isScrollButtonState({ up: false, down: false })).toBe(false);
});
});