mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-12-10 00:27:25 -06:00
Explicitly wrap in ContainerProvider when calling renderWithStore
This commit is contained in:
parent
514162964d
commit
d11358af59
@ -30,8 +30,11 @@ export const useDependencies = <T extends unknown[]>(...names: string[]): T => {
|
||||
}) as T;
|
||||
};
|
||||
|
||||
type Optionalize<P, K extends keyof P> = Omit<P, K> & Partial<Pick<P, K>>;
|
||||
|
||||
/**
|
||||
* Higher Order Component used to inject services into components as props.
|
||||
* All dependencies become optional props so that they can still be explicitly set in tests if desired.
|
||||
*/
|
||||
export function withDependencies<
|
||||
Props extends Record<string, unknown>,
|
||||
@ -39,16 +42,16 @@ export function withDependencies<
|
||||
>(
|
||||
Component: ComponentType<Props>,
|
||||
dependencyNames: DependencyName[],
|
||||
): ComponentType<Omit<Props, DependencyName>> {
|
||||
): ComponentType<Optionalize<Props, DependencyName>> {
|
||||
function Wrapper(props: Omit<Props, DependencyName>) {
|
||||
const container = useContainer('withDependencies');
|
||||
const container = useContext(ContainerContext);
|
||||
|
||||
// Inject services, unless they have been overridden by props passed from
|
||||
// the parent component.
|
||||
const dependencies: Partial<Record<DependencyName, unknown>> = {};
|
||||
for (const dependency of dependencyNames) {
|
||||
if (!(dependency in props)) {
|
||||
dependencies[dependency] = container[dependency];
|
||||
dependencies[dependency] = container?.[dependency];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import type { ShlinkApiClient } from '@shlinkio/shlink-js-sdk';
|
||||
import type { RenderOptions } from '@testing-library/react';
|
||||
import { render } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import type { PropsWithChildren, ReactElement } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { RootState } from '../../src/store';
|
||||
import { setUpStore } from '../../src/store';
|
||||
|
||||
@ -12,15 +15,33 @@ export const renderWithEvents = (element: ReactElement, options?: RenderOptions)
|
||||
});
|
||||
|
||||
export type RenderOptionsWithState = Omit<RenderOptions, 'wrapper'> & {
|
||||
/** Initial state for the redux store */
|
||||
initialState?: Partial<RootState>;
|
||||
|
||||
/**
|
||||
* If provided, it will set this as the `buildShlinkApiClient` dependency in the `ContainerProvider`.
|
||||
* If more dependencies are needed, then explicitly define your own `ContainerProvider` and make sure it includes a
|
||||
* `buildShlinkApiClient` service.
|
||||
*
|
||||
* Defaults to vi.fn()
|
||||
*/
|
||||
buildShlinkApiClient?: () => ShlinkApiClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render provided ReactElement wrapped in a redux `Provider` and a `ContainerProvider` with a single
|
||||
* `buildShlinkApiClient` dependency.
|
||||
*/
|
||||
export const renderWithStore = (
|
||||
element: ReactElement,
|
||||
{ initialState = {}, ...options }: RenderOptionsWithState = {},
|
||||
{ initialState = {}, buildShlinkApiClient = vi.fn(), ...options }: RenderOptionsWithState = {},
|
||||
) => {
|
||||
const store = setUpStore(initialState);
|
||||
const Wrapper = ({ children }: PropsWithChildren) => <Provider store={store}>{children}</Provider>;
|
||||
const Wrapper = ({ children }: PropsWithChildren) => (
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient })}>
|
||||
<Provider store={store}>{children}</Provider>
|
||||
</ContainerProvider>
|
||||
);
|
||||
|
||||
return {
|
||||
store,
|
||||
|
||||
@ -2,7 +2,6 @@ import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { Home } from '../../src/common/Home';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
import { renderWithStore } from '../__helpers__/setUpTest';
|
||||
@ -10,9 +9,7 @@ import { renderWithStore } from '../__helpers__/setUpTest';
|
||||
describe('<Home />', () => {
|
||||
const setUp = (servers: ServersMap = {}) => renderWithStore(
|
||||
<MemoryRouter>
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<Home />
|
||||
</ContainerProvider>
|
||||
<Home />
|
||||
</MemoryRouter>,
|
||||
{
|
||||
initialState: { servers },
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { Router } from 'react-router';
|
||||
import { MainHeader } from '../../src/common/MainHeader';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
import { renderWithStore } from '../__helpers__/setUpTest';
|
||||
|
||||
@ -14,9 +12,7 @@ describe('<MainHeader />', () => {
|
||||
|
||||
return renderWithStore(
|
||||
<Router location={history.location} navigator={history}>
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<MainHeader />
|
||||
</ContainerProvider>
|
||||
<MainHeader />
|
||||
</Router>,
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
import { renderWithStore } from '../__helpers__/setUpTest';
|
||||
|
||||
describe('<ShlinkVersionsContainer />', () => {
|
||||
const setUp = (selectedServer: SelectedServer = null) => renderWithStore(
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<ShlinkVersionsContainer />
|
||||
</ContainerProvider>,
|
||||
{
|
||||
initialState: { selectedServer },
|
||||
},
|
||||
);
|
||||
const setUp = (selectedServer: SelectedServer = null) => renderWithStore(<ShlinkVersionsContainer />, {
|
||||
initialState: { selectedServer },
|
||||
});
|
||||
|
||||
it.each([
|
||||
[null],
|
||||
|
||||
@ -2,7 +2,6 @@ import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { ShlinkWebComponentContainer } from '../../src/common/ShlinkWebComponentContainer';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../src/servers/data';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
import { renderWithStore } from '../__helpers__/setUpTest';
|
||||
@ -16,12 +15,7 @@ vi.mock('@shlinkio/shlink-web-component', () => ({
|
||||
describe('<ShlinkWebComponentContainer />', () => {
|
||||
const setUp = (selectedServer: SelectedServer) => renderWithStore(
|
||||
<MemoryRouter>
|
||||
<ContainerProvider value={fromPartial({
|
||||
buildShlinkApiClient: vi.fn(),
|
||||
TagColorsStorage: fromPartial({}),
|
||||
})}>
|
||||
<ShlinkWebComponentContainer />
|
||||
</ContainerProvider>
|
||||
<ShlinkWebComponentContainer TagColorsStorage={fromPartial({})} />
|
||||
</MemoryRouter>,
|
||||
{
|
||||
initialState: { selectedServer, servers: {}, settings: {} },
|
||||
|
||||
@ -2,7 +2,6 @@ import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { Router } from 'react-router';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import { CreateServer } from '../../src/servers/CreateServer';
|
||||
import type { ServersMap } from '../../src/servers/data';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
@ -31,13 +30,7 @@ describe('<CreateServer />', () => {
|
||||
history,
|
||||
...renderWithStore(
|
||||
<Router location={history.location} navigator={history}>
|
||||
<ContainerProvider value={fromPartial({
|
||||
ImportServersBtn: () => <>ImportServersBtn</>,
|
||||
useTimeoutToggle,
|
||||
buildShlinkApiClient: vi.fn(),
|
||||
})}>
|
||||
<CreateServer />
|
||||
</ContainerProvider>
|
||||
<CreateServer useTimeoutToggle={useTimeoutToggle} />
|
||||
</Router>,
|
||||
{
|
||||
initialState: { servers },
|
||||
|
||||
@ -2,7 +2,6 @@ import { fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { Router } from 'react-router';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||
import { isServerWithId } from '../../src/servers/data';
|
||||
import { EditServer } from '../../src/servers/EditServer';
|
||||
@ -22,9 +21,7 @@ describe('<EditServer />', () => {
|
||||
history,
|
||||
...renderWithStore(
|
||||
<Router location={history.location} navigator={history}>
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<EditServer />
|
||||
</ContainerProvider>
|
||||
<EditServer />
|
||||
</Router>,
|
||||
{
|
||||
initialState: {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { ServersMap, ServerWithId } from '../../src/servers/data';
|
||||
import { ManageServers } from '../../src/servers/ManageServers';
|
||||
import type { ServersExporter } from '../../src/servers/services/ServersExporter';
|
||||
@ -17,14 +16,7 @@ describe('<ManageServers />', () => {
|
||||
);
|
||||
const setUp = (servers: ServersMap = {}) => renderWithStore(
|
||||
<MemoryRouter>
|
||||
<ContainerProvider value={fromPartial({
|
||||
ServersExporter: serversExporter,
|
||||
ImportServersBtn: () => <span>ImportServersBtn</span>,
|
||||
useTimeoutToggle,
|
||||
buildShlinkApiClient: vi.fn(),
|
||||
})}>
|
||||
<ManageServers />
|
||||
</ContainerProvider>
|
||||
<ManageServers useTimeoutToggle={useTimeoutToggle} ServersExporter={serversExporter} />
|
||||
</MemoryRouter>,
|
||||
{
|
||||
initialState: { servers },
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { ContainerProvider } from '../../src/container/context';
|
||||
import type { ServersMap } from '../../src/servers/data';
|
||||
import { ServersDropdown } from '../../src/servers/ServersDropdown';
|
||||
import { checkAccessibility } from '../__helpers__/accessibility';
|
||||
@ -15,11 +14,9 @@ describe('<ServersDropdown />', () => {
|
||||
};
|
||||
const setUp = (servers: ServersMap = fallbackServers) => renderWithStore(
|
||||
<MemoryRouter>
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<ul role="menu">
|
||||
<ServersDropdown />
|
||||
</ul>
|
||||
</ContainerProvider>
|
||||
<ul role="menu">
|
||||
<ServersDropdown />
|
||||
</ul>
|
||||
</MemoryRouter>,
|
||||
{
|
||||
initialState: { selectedServer: null, servers },
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { ContainerProvider } from '../../../src/container/context';
|
||||
import type { ServerData, ServersMap, ServerWithId } from '../../../src/servers/data';
|
||||
import type { ImportServersBtnProps } from '../../../src/servers/helpers/ImportServersBtn';
|
||||
import { ImportServersBtn } from '../../../src/servers/helpers/ImportServersBtn';
|
||||
@ -14,9 +13,7 @@ describe('<ImportServersBtn />', () => {
|
||||
const importServersFromFile = vi.fn().mockResolvedValue([]);
|
||||
const serversImporterMock = fromPartial<ServersImporter>({ importServersFromFile });
|
||||
const setUp = (props: Partial<ImportServersBtnProps> = {}, servers: ServersMap = {}) => renderWithStore(
|
||||
<ContainerProvider value={fromPartial({ ServersImporter: serversImporterMock })}>
|
||||
<ImportServersBtn {...props} onImport={onImportMock} />
|
||||
</ContainerProvider>,
|
||||
<ImportServersBtn {...props} onImport={onImportMock} ServersImporter={serversImporterMock} />,
|
||||
{
|
||||
initialState: { servers },
|
||||
},
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { screen } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { ContainerProvider } from '../../../src/container/context';
|
||||
import type { NonReachableServer, NotFoundServer, SelectedServer } from '../../../src/servers/data';
|
||||
import { ServerError } from '../../../src/servers/helpers/ServerError';
|
||||
import { checkAccessibility } from '../../__helpers__/accessibility';
|
||||
@ -10,9 +9,7 @@ import { renderWithStore } from '../../__helpers__/setUpTest';
|
||||
describe('<ServerError />', () => {
|
||||
const setUp = (selectedServer: SelectedServer) => renderWithStore(
|
||||
<MemoryRouter>
|
||||
<ContainerProvider value={fromPartial({ buildShlinkApiClient: vi.fn() })}>
|
||||
<ServerError />
|
||||
</ContainerProvider>
|
||||
<ServerError />
|
||||
</MemoryRouter>,
|
||||
{
|
||||
initialState: { selectedServer, servers: {} },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user