import { jest } from '@jest/globals'; import { waitFor } from '@testing-library/react'; import type { ComponentType } from 'react'; import React from 'react'; import { BindingsConsumer, useBinding } from 'react-bindings'; import { runInDom } from '../../__test_dependency__/run-in-dom.js'; import { sleep } from '../../__test_dependency__/sleep.js'; import type { Waitable } from '../../waitable/types/waitable'; import type { WaitablePrimaryFunction } from '../types/primary-function'; import { useWaitable } from '../use-waitable.js'; describe('useWaitable', () => { it("waitable shouldn't rerun unnecessarily on rerender", () => runInDom(({ onMount }) => { const refresh = useBinding(() => 0, { id: 'refresh' }); let waitable: Waitable | undefined; const waitablePrimaryFunc = jest.fn>(async ({ setSuccess }) => { await sleep(50); setSuccess(1); }); const MyComponent: ComponentType = jest.fn(() => { waitable = useWaitable(waitablePrimaryFunc, { id: 'test' }); return <>; }); onMount(async () => { expect(waitable?.error.get()).toBeUndefined(); expect(waitable?.value.get()).toBeUndefined(); await waitFor(() => expect(waitable?.value.get()).toBe(1)); expect(waitable?.error.get()).toBeUndefined(); expect(MyComponent).toHaveBeenCalledTimes(1); expect(waitablePrimaryFunc).toHaveBeenCalledTimes(1); refresh.set(1); await expect(waitFor(() => expect(waitable?.value.get()).not.toBe(1))).rejects.toThrow(); expect(waitable?.error.get()).toBeUndefined(); expect(waitablePrimaryFunc).toHaveBeenCalledTimes(1); expect(MyComponent).toHaveBeenCalledTimes(2); }); return {() => }; })); it('waitable should rerun on rerender if deps change', () => runInDom(({ onMount }) => { const refresh = useBinding(() => 0, { id: 'refresh' }); let waitable: Waitable | undefined; const waitablePrimaryFunc = jest.fn>(async ({ setSuccess }) => { await sleep(50); setSuccess(1); }); const MyComponent: ComponentType<{ value: number }> = jest.fn(({ value }: { value: number }) => { waitable = useWaitable(waitablePrimaryFunc, { id: 'test', deps: [value] }); return <>; }); onMount(async () => { expect(waitable?.error.get()).toBeUndefined(); expect(waitable?.value.get()).toBeUndefined(); await waitFor(() => expect(waitable?.value.get()).toBe(1)); expect(waitable?.error.get()).toBeUndefined(); expect(MyComponent).toHaveBeenCalledTimes(1); expect(waitablePrimaryFunc).toHaveBeenCalledTimes(1); refresh.set(1); await waitFor(() => expect(waitablePrimaryFunc).toHaveBeenCalledTimes(2)); expect(waitable?.error.get()).toBeUndefined(); expect(MyComponent).toHaveBeenCalledTimes(2); }); return {({ refresh: value }) => }; })); });