import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { onTapCode } from '../src/lib/tap-code.js'; const tap = (node) => node.dispatchEvent(new Event('click')); beforeEach(() => vi.useFakeTimers()); afterEach(() => vi.useRealTimers()); describe('onTapCode', () => { it('fires after `count` taps inside the window', () => { const node = new EventTarget(); const fn = vi.fn(); onTapCode(node, fn, { count: 7, windowMs: 1500 }); for (let i = 0; i < 6; i++) tap(node); expect(fn).not.toHaveBeenCalled(); tap(node); expect(fn).toHaveBeenCalledTimes(1); }); it('resets when taps are too far apart', () => { const node = new EventTarget(); const fn = vi.fn(); onTapCode(node, fn, { count: 3, windowMs: 500 }); tap(node); tap(node); vi.advanceTimersByTime(600); // window elapsed -> counter clears tap(node); tap(node); expect(fn).not.toHaveBeenCalled(); tap(node); expect(fn).toHaveBeenCalledTimes(1); }); it('unbind stops it', () => { const node = new EventTarget(); const fn = vi.fn(); const off = onTapCode(node, fn, { count: 2 }); off(); tap(node); tap(node); expect(fn).not.toHaveBeenCalled(); }); });