import { jest } from '@jest/globals'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { runInDom } from '../../__test_dependency__/run-in-dom.js'; import { sleep } from '../../__test_dependency__/sleep.js'; import { useBinding } from '../../binding/use-binding.js'; import { BindingsConsumer } from '../../components/BindingsConsumer/index.js'; import { useBindingEffect } from '../use-binding-effect.js'; describe('useBindingEffect', () => { it('with triggerOnMount=false, callback should not be run on mount even if bindings changed between render and mount', () => runInDom(({ onMount }) => { const b = useBinding(() => 0, { id: 'test' }); const callback = jest.fn(({ b }: { b: number }) => { expect(b).toBe(1); }); useBindingEffect({ b }, callback, { triggerOnMount: false }); b.set(1); onMount(async () => { await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(0); b.set(1); await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(1); }); })); it('with triggerOnMount=true, callback should always be made on mount', () => runInDom(({ onMount }) => { const b = useBinding(() => 0, { id: 'test' }); const callback = jest.fn(({ b: _b }: { b: number }) => {}); const refreshValue = useBinding(() => 0, { id: 'refreshValue' }); const MyComponent = () => { useBindingEffect({ b }, callback, { triggerOnMount: true }); return <>; }; onMount(async () => { await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(1); b.set(1); await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(2); refreshValue.set(1); await waitFor(() => expect(callback).toHaveBeenCalledTimes(3)); }); return {() => }; })); it('with triggerOnMount=first, callback should be made only on the first mount', () => runInDom(({ onMount }) => { const b = useBinding(() => 0, { id: 'test' }); const callback = jest.fn(({ b: _b }: { b: number }) => {}); const refreshValue = useBinding(() => 0, { id: 'refreshValue' }); const MyComponent = () => { useBindingEffect({ b }, callback, { triggerOnMount: 'first' }); return <>; }; onMount(async () => { await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(1); b.set(1); await waitFor(() => expect(callback).toHaveBeenCalledTimes(2)); refreshValue.set(1); await expect(waitFor(() => expect(callback).not.toHaveBeenCalledTimes(2))).rejects.toThrow(); }); return {() => }; })); it('with deps, callback should be made only on the first mount or if the dependency values change', () => runInDom(({ onMount }) => { const callback = jest.fn(() => {}); const refreshValue = useBinding(() => 0, { id: 'refreshValue' }); const MyComponent = ({ value }: { value: number }) => { useBindingEffect(undefined, callback, { deps: [value], limitType: 'none' }); return <>; }; onMount(async () => { await sleep(50); // giving time for callback expect(callback).toHaveBeenCalledTimes(0); refreshValue.set(0); await expect(waitFor(() => expect(callback).not.toHaveBeenCalledTimes(0))).rejects.toThrow(); refreshValue.set(1); await waitFor(() => expect(callback).toHaveBeenCalledTimes(1)); refreshValue.set(1); await expect(waitFor(() => expect(callback).not.toHaveBeenCalledTimes(1))).rejects.toThrow(); refreshValue.set(2); await waitFor(() => expect(callback).toHaveBeenCalledTimes(2)); }); return {(refreshValue) => }; })); });