import { fireEvent, render, } from '@testing-library/react';
import { jsdomReactUniDriver } from '@wix/unidriver-jsdom-react';
import { act } from '../unidriver/actCompat';
const getElement = ({ rendered, dataHook, }) => {
    const element = dataHook
        ? rendered.container.querySelector(`[data-hook="${dataHook}"]`)
        : rendered.container.firstElementChild;
    return element;
};
function createAsyncRendererBase(createDriver, defaultOptions) {
    return async (jsx, options = defaultOptions) => {
        const { dataHook, ...reactTestingLibraryOptions } = {
            ...defaultOptions,
            ...options,
        };
        let renderResult;
        await act(async () => {
            renderResult = render(jsx, reactTestingLibraryOptions);
        });
        // non-null/undef assertion used here because renderResult is already assigned
        const rendered = renderResult;
        const element = getElement({ rendered, dataHook });
        const actWrappedRerender = async (jsxElement) => {
            await act(async () => {
                rendered.rerender(jsxElement);
            });
        };
        return {
            ...rendered,
            rerender: actWrappedRerender,
            driver: createDriver({ rendered, element, component: jsx, dataHook }),
        };
    };
}
function createRendererBase(createDriver, defaultOptions) {
    return (jsx, options = defaultOptions) => {
        const { dataHook, ...reactTestingLibraryOptions } = {
            ...defaultOptions,
            ...options,
        };
        const rendered = render(jsx, reactTestingLibraryOptions);
        const element = getElement({ rendered, dataHook });
        return {
            ...rendered,
            driver: createDriver({ rendered, element, component: jsx, dataHook }),
        };
    };
}
/**
 * Creates a `render` function that returns the same object as `@testing-library/react`'s render, but
 * with and extra `driver` property. Designed for usage with legacy drivers. Deprecated.
 *
 * The returned render function arguments:
 * @param {React.Element} driverFactory jsx a jsx element to render
 * @param {object} defaultOptions render-options for @testing-library/react. The options may also contain a `dataHook` prop which if provided then the driver would be created with the element which is found by the dataHook. If not provided then it assumes that the rendered root element is the component's root element and it will be used for the driver.
 */
export function createRendererWithDriver(driverFactory, defaultOptions = {}) {
    const createDriver = ({ rendered, element, dataHook, }) => driverFactory({
        element: element,
        wrapper: rendered.container,
        eventTrigger: fireEvent,
        dataHook: dataHook,
    });
    return createRendererBase(createDriver, defaultOptions);
}
function driverFactoryWrapper(driverFactory) {
    return ({ element, dataHook }) => driverFactory(
    // non-null/undef assertion used here because of wrong external types, element CAN be null here
    jsdomReactUniDriver(element), jsdomReactUniDriver(document.body), 
    // non-null/undef assertion used here because of wrong external types, dataHook is optional
    { dataHook: dataHook });
}
/**
 * Creates a `render` function that returns the same object as `@testing-library/react`'s render, but
 * with and extra `driver` property which is a Unidriver.
 *
 * The returned render function arguments:
 * @param {React.Element} driverFactory jsx a jsx element to render
 * @param {object} defaultOptions render-options for @testing-library/react. The options may also contain a `dataHook` prop which if provided then the driver would be created with the element which is found by the dataHook.
 * If not provided then it assumes that the rendered root element is the component's root element and it will be used for the driver.
 */
export function createRendererWithUniDriver(driverFactory, defaultOptions = {}) {
    const createDriver = driverFactoryWrapper(driverFactory);
    return createRendererBase(createDriver, defaultOptions);
}
/**
 * Creates a `render` function that returns Promise of the same object as `@testing-library/react`'s render, but
 * with and extra `driver` property which is a Unidriver. Internally wraps 'render' with async 'act', to settle the async state updates after component renders.
 *
 * The returned render function arguments:
 * @param {React.Element} driverFactory a jsx element to render
 * @param {object} defaultOptions render-options for @testing-library/react. The options may also contain a `dataHook` prop which if provided then the driver would be created with the element which is found by the dataHook. If not provided then it assumes that the rendered root element is the component's root element and it will be used for the driver.
 */
export function createAsyncRendererWithUniDriver(driverFactory, defaultOptions = {}) {
    const createDriver = driverFactoryWrapper(driverFactory);
    return createAsyncRendererBase(createDriver, defaultOptions);
}
export * from '@testing-library/react';
export * from './runAbsolutelyAllTimers';
//# sourceMappingURL=index.js.map