import { debounce } from './debounce';

describe('debounce', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.clearAllTimers();
    jest.useRealTimers();
  });

  test('should delay the execution of the function', () => {
    const mockFn = jest.fn();
    const debouncedFn = debounce(mockFn, 100);

    debouncedFn();
    expect(mockFn).not.toBeCalled();

    jest.advanceTimersByTime(50);
    debouncedFn();
    expect(mockFn).not.toBeCalled();

    jest.advanceTimersByTime(100);
    debouncedFn();
    expect(mockFn).toBeCalledTimes(1);
  });

  test('should debounce multiple invocations', () => {
    const mockFn = jest.fn();
    const debouncedFn = debounce(mockFn, 100);

    debouncedFn();
    debouncedFn();
    debouncedFn();
    expect(mockFn).not.toBeCalled();

    jest.advanceTimersByTime(200);
    expect(mockFn).toBeCalledTimes(1);
  });

  test('should pass the most recent argument to the debounced function', () => {
    const mockFn = jest.fn();
    const debouncedFn = debounce(mockFn, 100);

    debouncedFn(123);
    debouncedFn('abc');
    expect(mockFn).not.toBeCalled();

    jest.advanceTimersByTime(100);
    expect(mockFn).toBeCalledWith('abc');
  });
});
