import React, { useState } from 'react';
import { render, renderHook } from '@testing-library/react';
import { uniTestkitFactoryCreator } from '@wix/wix-ui-test-utils/testing-library';
import { act } from '../../utils/test-utils/react';
import useDebouncedCallback from './useDebouncedCallback';
import Box from '../../Box';
import Text from '../../Text';
import Button from '../../Button';
import { buttonDriverFactory } from '../../Button/Button.uni.driver';
import { textUniDriverFactory } from '../../Text/Text.uni.driver';
import { debounce } from '../../utils/test-utils/unit';
const dataHooks = {
    count: 'test-component-count',
    button: 'test-component-button',
};
const ButtonTestkit = uniTestkitFactoryCreator(buttonDriverFactory);
const TextTestkit = uniTestkitFactoryCreator(textUniDriverFactory);
const TestComponent = ({ onClick, debounceMs }) => {
    const [counter, setCounter] = useState(0);
    const debouncedIncreaseCounter = useDebouncedCallback(() => {
        const newCount = counter + 1;
        setCounter(newCount);
        if (onClick) {
            onClick(newCount);
        }
    }, [onClick, counter, setCounter], debounceMs, 
    // default lodash debounce doesn't work with jest fake timers
    debounce);
    return (React.createElement(Box, null,
        React.createElement(Text, { dataHook: dataHooks.count }, counter),
        React.createElement(Button, { dataHook: dataHooks.button, onClick: debouncedIncreaseCounter }, "Increase")));
};
vi.useFakeTimers();
describe('useDebouncedCallback', () => {
    it('debounces calls to provided callback', async () => {
        const debounceDelay = 200;
        const onClick = vi.fn();
        const { container } = render(React.createElement(TestComponent, { debounceMs: debounceDelay, onClick: onClick }));
        const buttonTestkit = ButtonTestkit({
            wrapper: container,
            dataHook: dataHooks.button,
        });
        const textTestkit = TextTestkit({
            wrapper: container,
            dataHook: dataHooks.count,
        });
        expect(await textTestkit.getText()).toBe('0');
        await buttonTestkit.click();
        await buttonTestkit.click();
        act(() => vi.advanceTimersByTime(debounceDelay));
        expect(onClick).toHaveBeenCalledTimes(1);
        expect(onClick).toHaveBeenNthCalledWith(1, 1);
        expect(await textTestkit.getText()).toBe('1');
    });
    it('updates function when dependencies change', async () => {
        const debounceDelay = 200;
        const onClick = vi.fn();
        const { container } = render(React.createElement(TestComponent, { debounceMs: debounceDelay, onClick: onClick }));
        const buttonTestkit = ButtonTestkit({
            wrapper: container,
            dataHook: dataHooks.button,
        });
        const textTestkit = TextTestkit({
            wrapper: container,
            dataHook: dataHooks.count,
        });
        await buttonTestkit.click();
        await buttonTestkit.click();
        act(() => vi.advanceTimersByTime(debounceDelay));
        await buttonTestkit.click();
        await buttonTestkit.click();
        act(() => vi.advanceTimersByTime(debounceDelay));
        expect(onClick).toHaveBeenCalledTimes(2);
        expect(onClick).toHaveBeenNthCalledWith(1, 1);
        expect(onClick).toHaveBeenNthCalledWith(2, 2);
        expect(await textTestkit.getText()).toBe('2');
    });
    it('creates new callback when debounce delay changes', async () => {
        const fn = vi.fn();
        const { result, rerender } = renderHook(({ debounceMs = 200 } = {}) => useDebouncedCallback(fn, [], debounceMs, debounce));
        const debouncedCallback = result.current;
        rerender({ debounceMs: 500 });
        // Callback was changed when debounce delay changed
        expect(result.current).not.toBe(debouncedCallback);
        await act(async () => result.current());
        vi.advanceTimersByTime(200);
        // debounce duration is now longer
        expect(fn).not.toHaveBeenCalled();
        vi.advanceTimersByTime(300);
        expect(fn).toHaveBeenCalled();
    });
});
//# sourceMappingURL=useDebouncedCallback.spec.js.map