UNPKG

@zendesk/react-measure-timing-hooks

Version:

react hooks for measuring time to interactive and time to render of components

149 lines (125 loc) 4.54 kB
import { afterEach, beforeEach, describe, expect, it, vitest as jest, } from 'vitest' import { debounce, type DebouncedFn, type DebounceOptionsRef, DebounceReason, TimeoutReason, } from './debounce' describe('debounce', () => { let mockFn: jest.Mock let optionsRef: DebounceOptionsRef<readonly [string]> let debouncedFn: DebouncedFn<readonly [string]> beforeEach(() => { jest.useFakeTimers() mockFn = jest.fn() optionsRef = { fn: mockFn, debounceMs: 100, } debouncedFn = debounce(optionsRef) }) afterEach(() => { jest.useRealTimers() }) it('should call the debounced function once after the debounce period', () => { debouncedFn('test') expect(mockFn).not.toHaveBeenCalled() jest.advanceTimersByTime(100) expect(mockFn).toHaveBeenCalledWith('test', DebounceReason) }) it('should not call the debounced function if it is cancelled before the debounce period', () => { debouncedFn('test') expect(mockFn).not.toHaveBeenCalled() debouncedFn.cancel() jest.advanceTimersByTime(100) expect(mockFn).not.toHaveBeenCalled() }) it('should call the debounced function with the TimeoutReason if a timeout is set', () => { debouncedFn = debounce({ ...optionsRef, timeoutMs: 200 }) debouncedFn('test') expect(mockFn).not.toHaveBeenCalled() // keep timeout after regular debounce: mockFn.mockReturnValue(true) jest.advanceTimersByTime(200) expect(mockFn).toHaveBeenNthCalledWith(1, 'test', DebounceReason) expect(mockFn).toHaveBeenNthCalledWith(2, 'test', TimeoutReason) }) it('should reset the debounce function state', () => { debouncedFn('test') debouncedFn.reset() expect(debouncedFn.getIsScheduled()).toBe(false) expect(debouncedFn.reset()).toBeUndefined() jest.advanceTimersByTime(100) expect(mockFn).not.toHaveBeenCalled() }) it('should manually flush the debounced function', () => { debouncedFn('test') const wasFlushed = debouncedFn.flush() expect(wasFlushed).toBe(true) expect(mockFn).toHaveBeenCalledWith('test', 'manual') }) it('should not flush if there is nothing scheduled', () => { const wasFlushed = debouncedFn.flush() expect(wasFlushed).toBe(false) expect(mockFn).not.toHaveBeenCalled() }) it('should keep the timeout if the debounced function returns true', () => { mockFn.mockReturnValue(true) debouncedFn = debounce({ ...optionsRef, timeoutMs: 200 }) debouncedFn('test') jest.advanceTimersByTime(100) expect(mockFn).toHaveBeenCalledWith('test', DebounceReason) expect(debouncedFn.getIsScheduled()).toBe(true) }) it('should clear the timeout if the debounced function returns false', () => { mockFn.mockReturnValue(false) debouncedFn = debounce({ ...optionsRef, timeoutMs: 200 }) debouncedFn('test') jest.advanceTimersByTime(100) expect(mockFn).toHaveBeenCalledWith('test', DebounceReason) expect(debouncedFn.getIsScheduled()).toBe(false) }) it('should pass FlushReason as the last argument to the debounced function', () => { debouncedFn('test') jest.advanceTimersByTime(100) expect(mockFn).toHaveBeenCalledWith('test', DebounceReason) }) it('should correctly handle optionsRef being mutated after the debounced function was created', () => { debouncedFn('test') const otherMockFn = jest.fn() optionsRef.debounceMs = 200 optionsRef.timeoutMs = 300 optionsRef.fn = otherMockFn debouncedFn('test2') jest.advanceTimersByTime(100) expect(mockFn).not.toHaveBeenCalled() expect(otherMockFn).not.toHaveBeenCalled() jest.advanceTimersByTime(100) expect(mockFn).not.toHaveBeenCalled() expect(otherMockFn).toHaveBeenLastCalledWith('test2', DebounceReason) otherMockFn.mockReturnValue(true) debouncedFn('test3') jest.advanceTimersByTime(200) expect(mockFn).not.toHaveBeenCalled() expect(otherMockFn).toHaveBeenLastCalledWith('test3', DebounceReason) jest.advanceTimersByTime(100) expect(otherMockFn).toHaveBeenLastCalledWith('test3', TimeoutReason) }) it('should correctly call the underlying function once, even when run multiple times in a row with different arguments', () => { debouncedFn('test1') debouncedFn('test2') debouncedFn('test3') expect(mockFn).not.toHaveBeenCalled() jest.advanceTimersByTime(100) expect(mockFn).toHaveBeenCalledTimes(1) expect(mockFn).toHaveBeenCalledWith('test3', DebounceReason) }) })