import type { FederatedPointerEvent } from 'pixi.js'; import { describe, expect, it } from 'vitest'; import { followsPress, pressCount, pressOf } from '../../src/ui/clicks'; interface Press { time: number; x?: number; y?: number; button?: number; } const press = (p: Press): FederatedPointerEvent => ({ timeStamp: p.time, button: p.button ?? 0, global: { x: p.x ?? 100, y: p.y ?? 100 }, }) as unknown as FederatedPointerEvent; /** Counts a run of presses on one key. Each test uses its own key, so no run reaches the next. */ const counts = (key: unknown, presses: Press[]): number[] => presses.map((p) => pressCount(press(p), key)); describe('pressCount', () => { it('counts a second press on the same target as a double-click', () => { expect(counts('row-a', [{ time: 0 }, { time: 120 }])).toEqual([1, 2]); }); it('starts over when the presses are too far apart in time', () => { expect(counts('row-b', [{ time: 0 }, { time: 900 }])).toEqual([1, 1]); }); it('starts over when the pointer moved to another row', () => { expect(counts('row-c', [{ time: 0 }, { time: 100, y: 140 }])).toEqual([1, 1]); }); it('tolerates the wobble of a hand holding the mouse still', () => { expect(counts('row-d', [{ time: 0 }, { time: 100, x: 103, y: 102 }])).toEqual([1, 2]); }); it('does not join presses on different targets', () => { const first = pressCount(press({ time: 0 }), 'row-e'); const second = pressCount(press({ time: 100 }), 'row-f'); expect([first, second]).toEqual([1, 1]); }); it('does not join presses of different buttons', () => { expect(counts('row-g', [{ time: 0 }, { time: 100, button: 2 }])).toEqual([1, 1]); }); it('starts a new run after a double-click, so a second pair counts again', () => { // Folding a row open and shut again is two double-clicks in a row, well inside the window. expect(counts('row-h', [{ time: 0 }, { time: 100 }, { time: 200 }, { time: 300 }])).toEqual([1, 2, 1, 2]); }); }); describe('followsPress', () => { // The second press of a link's double-click lands on a rebuilt panel, so no key is compared (#221). const first = pressOf(press({ time: 0 })); it('joins a press soon after at the same spot', () => { expect(followsPress(first, press({ time: 300, x: 104 }))).toBe(true); }); it('does not join a late press or one elsewhere', () => { expect(followsPress(first, press({ time: 500 }))).toBe(false); expect(followsPress(first, press({ time: 100, y: 120 }))).toBe(false); }); });