Created
July 30, 2024 16:38
-
-
Save DanielBarbakadze/7ad00231ec8ee2371a83e6b046bfafe5 to your computer and use it in GitHub Desktop.
use-query-params mocked adapter for Vitest (ReactRouter6Adapter, typescript)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useContext } from 'react'; | |
import { | |
BrowserRouter, | |
useNavigate, | |
useLocation, | |
UNSAFE_NavigationContext, | |
UNSAFE_DataRouterContext, | |
} from 'react-router-dom'; | |
import { | |
type QueryParamAdapterComponent, | |
type QueryParamAdapter, | |
} from 'use-query-params'; | |
import { QueryParamProvider } from 'use-query-params'; | |
type ChildrenProps = { | |
children?: React.ReactNode; | |
}; | |
const ProvidersHoC = ({ children }: ChildrenProps) => ( | |
<BrowserRouter> | |
<QueryParamProvider adapter={MockReactRouter6Adapter}> | |
{children} | |
</QueryParamProvider> | |
</BrowserRouter> | |
); | |
export { ProvidersHoC }; | |
type Location = { | |
search?: string; | |
state?: unknown; | |
}; | |
type Adapter = { | |
location: Location; | |
replace(location: Location): void; | |
push(location: Location): void; | |
}; | |
type MockReactRouter6AdapterProps = { | |
readonly children: (adapter: QueryParamAdapter) => React.ReactElement | null; | |
}; | |
const MockReactRouter6Adapter: QueryParamAdapterComponent = ({ | |
children, | |
}: MockReactRouter6AdapterProps): React.ReactElement | null => { | |
const navigator = useContext(UNSAFE_NavigationContext)?.navigator; | |
const navigate = useNavigate(); | |
const router = useContext(UNSAFE_DataRouterContext)?.router; | |
const location = useLocation(); | |
const adapter: Adapter = { | |
replace(location2: Location) { | |
navigate(location2.search ?? '?', { | |
replace: true, | |
state: location2.state, | |
}); | |
}, | |
push(location2: Location) { | |
navigate(location2.search ?? '?', { | |
replace: false, | |
state: location2.state, | |
}); | |
}, | |
get location() { | |
return ( | |
router?.state?.location ?? | |
(navigator && 'location' in navigator | |
? navigator.location | |
: undefined) ?? | |
location | |
); | |
}, | |
}; | |
return <>{children(adapter as QueryParamAdapter)}</>; | |
}; |
This can be also a simpler implementation
import React from 'react';
type Location = {
readonly search: string;
readonly state?: any;
};
type Adapter = {
location: Location;
replace(location: Location): void;
push(location: Location): void;
};
type MockReactRouter6AdapterProps = {
readonly children: (adapter: Adapter) => React.ReactElement | null;
};
const MockReactRouter6Adapter = ({
children,
}: MockReactRouter6AdapterProps): React.ReactElement | null => {
const adapter: Adapter = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
replace(location2: Location) {
// Does nothing
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
push(location2: Location) {
// Does nothing
},
get location() {
return { search: '' };
},
};
return <>{children(adapter)}</>;
};
export { MockReactRouter6Adapter };
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Against prompted error: