All files / function debounce.ts

100% Statements 19/19
33.33% Branches 1/3
100% Functions 4/4
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49                                  1x 2x 1x 1x     2x 2x       1x 1x   1x 1x   1x 1x 1x   1x 1x   1x 1x 1x   1x      
/**
 * Creates a debounced function that delays invoking `func` until after `wait`
 * milliseconds have elapsed since the last time the debounced function was
 * invoked.
 *
 * @param func The function to debounce
 * @param wait The number of milliseconds to delay
 * @returns Returns the new debounced function
 *
 * {@link https://lodash.com/docs#debounce}
 */
export function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number = 0,
): (...args: Parameters<T>) => void {
  let timeoutId: ReturnType<typeof setTimeout> | undefined
 
  return function debounced(this: any, ...args: Parameters<T>): void {
    const later = () => {
      timeoutId = undefined
      func.apply(this, args)
    }
 
    clearTimeout(timeoutId)
    timeoutId = setTimeout(later, wait)
  }
}
 
Eif (import.meta.vitest) {
  const { test, expect, vi } = import.meta.vitest
 
  test('debounce', async () => {
    vi.useFakeTimers()
 
    const fn = vi.fn()
    const debounced = debounce(fn, 100)
    expect(fn).not.toHaveBeenCalled()
 
    debounced()
    expect(fn).not.toHaveBeenCalled()
 
    debounced()
    vi.advanceTimersByTime(100)
    expect(fn).toHaveBeenCalledTimes(1)
 
    vi.useRealTimers()
  })
}