import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { debounce } from './debounce'; describe('debounce', () => { beforeEach(() => { vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); it('does not fire before the delay has elapsed', () => { const fn = vi.fn(); const debounced = debounce(fn, 200); debounced(); vi.advanceTimersByTime(199); expect(fn).not.toHaveBeenCalled(); }); it('fires exactly once after the delay', () => { const fn = vi.fn(); const debounced = debounce(fn, 200); debounced(); vi.advanceTimersByTime(200); expect(fn).toHaveBeenCalledTimes(1); }); it('resets the timer on each call — fires only once after inactivity', () => { const fn = vi.fn(); const debounced = debounce(fn, 200); debounced(); vi.advanceTimersByTime(100); debounced(); vi.advanceTimersByTime(100); debounced(); vi.advanceTimersByTime(200); expect(fn).toHaveBeenCalledTimes(1); }); it('passes the latest arguments to the callback', () => { const fn = vi.fn(); const debounced = debounce(fn, 200); debounced('first'); debounced('second'); vi.advanceTimersByTime(200); expect(fn).toHaveBeenCalledWith('second'); }); it('can fire again after the first invocation settles', () => { const fn = vi.fn(); const debounced = debounce(fn, 200); debounced(); vi.advanceTimersByTime(200); debounced(); vi.advanceTimersByTime(200); expect(fn).toHaveBeenCalledTimes(2); }); });