import type { UrlUpdateEvent } from 'nuqs/adapters/testing' import type { ComponentProps, ReactElement, ReactNode } from 'react' import type { Mock } from 'vitest' import { render, renderHook } from '@testing-library/react' import { NuqsTestingAdapter } from 'nuqs/adapters/testing' import { vi } from 'vitest' type NuqsSearchParams = ComponentProps['searchParams'] type NuqsOnUrlUpdate = (event: UrlUpdateEvent) => void type NuqsOnUrlUpdateSpy = Mock type NuqsTestOptions = { searchParams?: NuqsSearchParams onUrlUpdate?: NuqsOnUrlUpdateSpy } type NuqsHookTestOptions = NuqsTestOptions & { initialProps?: Props } type NuqsWrapperProps = { children: ReactNode } export const createNuqsTestWrapper = (options: NuqsTestOptions = {}) => { const { searchParams = '', onUrlUpdate } = options const urlUpdateSpy = onUrlUpdate ?? vi.fn() const wrapper = ({ children }: NuqsWrapperProps) => ( {children} ) return { wrapper, onUrlUpdate: urlUpdateSpy, } } export const renderWithNuqs = (ui: ReactElement, options: NuqsTestOptions = {}) => { const { wrapper, onUrlUpdate } = createNuqsTestWrapper(options) const rendered = render(ui, { wrapper }) return { ...rendered, onUrlUpdate, } } export const renderHookWithNuqs = ( callback: (props: Props) => Result, options: NuqsHookTestOptions = {}, ) => { const { initialProps, ...nuqsOptions } = options const { wrapper, onUrlUpdate } = createNuqsTestWrapper(nuqsOptions) const rendered = renderHook(callback, { wrapper, initialProps }) return { ...rendered, onUrlUpdate, } }