import { mount } from 'enzyme'; import React from 'react'; import { useLatestCallback } from './useLatestCallback.hook'; const TestComponent = ({ callback, onCallbackChange, }: { callback: (...args: any) => any; onCallbackChange: (callback: Function) => any; }) => { const memoizedCallback = useLatestCallback(callback); onCallbackChange(memoizedCallback); return null as JSX.Element; }; describe('useLatestCallback', () => { it('should give back a stable function reference when the callback argument changes', () => { const callbacksFromHook: any[] = []; const onCallbackChange = (callback: any) => callbacksFromHook.push(callback); const component = mount( 'first'} onCallbackChange={onCallbackChange} />); component.setProps({ callback: () => 'second' }); expect(callbacksFromHook.length).toBe(2); expect(callbacksFromHook[0]).toBe(callbacksFromHook[1]); component.setProps({ callback: () => 'third' }); expect(callbacksFromHook.length).toBe(3); expect(callbacksFromHook[1]).toBe(callbacksFromHook[2]); }); it('should always call the latest callback argument', () => { let callbackFromHook: any; const onCallbackChange = (callback: any) => (callbackFromHook = callback); const initialCallback = jasmine.createSpy('initialCallback', () => 'initial'); const component = mount(); callbackFromHook(); expect(initialCallback).toHaveBeenCalledTimes(1); const updatedCallback = jasmine.createSpy('updatedCallback', () => 'updated'); component.setProps({ callback: updatedCallback }); callbackFromHook(); expect(initialCallback).toHaveBeenCalledTimes(1); expect(updatedCallback).toHaveBeenCalledTimes(1); }); it('should pass through the arguments/return value of the original callback', () => { let callbackFromHook: any; const onCallbackChange = (callback: any) => (callbackFromHook = callback); mount( `Hello ${value}`} onCallbackChange={onCallbackChange} />); const returnValue = callbackFromHook('World'); expect(returnValue).toBe('Hello World'); }); });