diff --git a/src/container/context.tsx b/src/container/context.tsx index a1131943..35e7c5ef 100644 --- a/src/container/context.tsx +++ b/src/container/context.tsx @@ -30,8 +30,11 @@ export const useDependencies = (...names: string[]): T => { }) as T; }; +type Optionalize = Omit & Partial>; + /** * 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, @@ -39,16 +42,16 @@ export function withDependencies< >( Component: ComponentType, dependencyNames: DependencyName[], -): ComponentType> { +): ComponentType> { function Wrapper(props: Omit) { - 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> = {}; for (const dependency of dependencyNames) { if (!(dependency in props)) { - dependencies[dependency] = container[dependency]; + dependencies[dependency] = container?.[dependency]; } } diff --git a/test/__helpers__/setUpTest.tsx b/test/__helpers__/setUpTest.tsx index 91763f86..62a29ceb 100644 --- a/test/__helpers__/setUpTest.tsx +++ b/test/__helpers__/setUpTest.tsx @@ -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 & { + /** Initial state for the redux store */ initialState?: Partial; + + /** + * 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) => {children}; + const Wrapper = ({ children }: PropsWithChildren) => ( + + {children} + + ); return { store, diff --git a/test/common/Home.test.tsx b/test/common/Home.test.tsx index e9521d20..84b36a5f 100644 --- a/test/common/Home.test.tsx +++ b/test/common/Home.test.tsx @@ -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('', () => { const setUp = (servers: ServersMap = {}) => renderWithStore( - - - + , { initialState: { servers }, diff --git a/test/common/MainHeader.test.tsx b/test/common/MainHeader.test.tsx index e9614c6a..e70f755d 100644 --- a/test/common/MainHeader.test.tsx +++ b/test/common/MainHeader.test.tsx @@ -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('', () => { return renderWithStore( - - - + , ); }; diff --git a/test/common/ShlinkVersionsContainer.test.tsx b/test/common/ShlinkVersionsContainer.test.tsx index ba9c9dc2..8a99b3c1 100644 --- a/test/common/ShlinkVersionsContainer.test.tsx +++ b/test/common/ShlinkVersionsContainer.test.tsx @@ -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('', () => { - const setUp = (selectedServer: SelectedServer = null) => renderWithStore( - - - , - { - initialState: { selectedServer }, - }, - ); + const setUp = (selectedServer: SelectedServer = null) => renderWithStore(, { + initialState: { selectedServer }, + }); it.each([ [null], diff --git a/test/common/ShlinkWebComponentContainer.test.tsx b/test/common/ShlinkWebComponentContainer.test.tsx index fb31f69d..f120630a 100644 --- a/test/common/ShlinkWebComponentContainer.test.tsx +++ b/test/common/ShlinkWebComponentContainer.test.tsx @@ -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('', () => { const setUp = (selectedServer: SelectedServer) => renderWithStore( - - - + , { initialState: { selectedServer, servers: {}, settings: {} }, diff --git a/test/servers/CreateServer.test.tsx b/test/servers/CreateServer.test.tsx index 2905b783..bf6d0b7b 100644 --- a/test/servers/CreateServer.test.tsx +++ b/test/servers/CreateServer.test.tsx @@ -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('', () => { history, ...renderWithStore( - <>ImportServersBtn, - useTimeoutToggle, - buildShlinkApiClient: vi.fn(), - })}> - - + , { initialState: { servers }, diff --git a/test/servers/EditServer.test.tsx b/test/servers/EditServer.test.tsx index 62b46252..8c4ed7b4 100644 --- a/test/servers/EditServer.test.tsx +++ b/test/servers/EditServer.test.tsx @@ -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('', () => { history, ...renderWithStore( - - - + , { initialState: { diff --git a/test/servers/ManageServers.test.tsx b/test/servers/ManageServers.test.tsx index f9395816..99daa772 100644 --- a/test/servers/ManageServers.test.tsx +++ b/test/servers/ManageServers.test.tsx @@ -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('', () => { ); const setUp = (servers: ServersMap = {}) => renderWithStore( - ImportServersBtn, - useTimeoutToggle, - buildShlinkApiClient: vi.fn(), - })}> - - + , { initialState: { servers }, diff --git a/test/servers/ServersDropdown.test.tsx b/test/servers/ServersDropdown.test.tsx index d98a3a6f..b2668bd5 100644 --- a/test/servers/ServersDropdown.test.tsx +++ b/test/servers/ServersDropdown.test.tsx @@ -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('', () => { }; const setUp = (servers: ServersMap = fallbackServers) => renderWithStore( - -
    - -
-
+
    + +
, { initialState: { selectedServer: null, servers }, diff --git a/test/servers/helpers/ImportServersBtn.test.tsx b/test/servers/helpers/ImportServersBtn.test.tsx index aa3a5cdd..c29992fb 100644 --- a/test/servers/helpers/ImportServersBtn.test.tsx +++ b/test/servers/helpers/ImportServersBtn.test.tsx @@ -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('', () => { const importServersFromFile = vi.fn().mockResolvedValue([]); const serversImporterMock = fromPartial({ importServersFromFile }); const setUp = (props: Partial = {}, servers: ServersMap = {}) => renderWithStore( - - - , + , { initialState: { servers }, }, diff --git a/test/servers/helpers/ServerError.test.tsx b/test/servers/helpers/ServerError.test.tsx index 95e6693a..3a3aff9d 100644 --- a/test/servers/helpers/ServerError.test.tsx +++ b/test/servers/helpers/ServerError.test.tsx @@ -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('', () => { const setUp = (selectedServer: SelectedServer) => renderWithStore( - - - + , { initialState: { selectedServer, servers: {} },